Home > database >  How to make OnControllerColliderHit method to detect collision only once?
How to make OnControllerColliderHit method to detect collision only once?

Time:12-30

OnControllerColliderHit method detects collision every frame. I want it to be called only once when I touch another object with collider.

Here is an example of what I have right now. Look at collision counter down below: https://youtu.be/-2t45tkWTc8

I want OnControllerColliderHit method to be like OnCollisionEnter.

My CollisionDetection script:

public class SphereCollisionHandler : MonoBehaviour
{
    
    private int collisionCounter;

    [SerializeField] private GameObject gameObj;
    private TMP_Text textMesh;

    void Start ()
    {
        textMesh = gameObj.GetComponent<TMP_Text>();
    }

    void OnControllerColliderHit(ControllerColliderHit hit)
    {
        if (hit.gameObject.tag == "Cube")
        {
            collisionCounter = collisionCounter   1;
            textMesh.text = collisionCounter.ToString();
        }
    }
}

I've already tried to use OnCollisionEnter, but it works bad with a Player Object that has CharacterController.

CodePudding user response:

The API OnControllerColliderHit indeed sounds like it makes sense that this is called every frame while moving.

This can be used to push objects when they collide with the character.


If you want to get it only once in total simply add a flag

private bool alreadyHit;

and then do

void OnControllerColliderHit(ControllerColliderHit hit)
{
    if(alreadyHit) return;

    if (hit.gameObject.CompareTag("Cube"))
    {
        alreadyHit = true;

        collisionCounter = collisionCounter   1;
        textMesh.text = collisionCounter.ToString();
    }
}

Or if your goal is rather tracking every hit with each object once you could use something like

private readonly HashSet<GameObject> alreadyCollidedWith = new HashSet<GameObject>();

and then

void OnControllerColliderHit(ControllerColliderHit hit)
{
    if (hit.gameObject.CompareTag("Cube") && !alreadyCollidedWith.Contains(hit.gameObject))
    {
        alreadyCollidedWith.Add(hit.gameObject);

        collisionCounter = collisionCounter   1;
        textMesh.text = collisionCounter.ToString();
    }
}
  • Related