Issue with collisions and input

I’m using this code try to make a pick up system in 3D. Collsion works but input does not. I’m pretty knew and need help please.

  public GameObject camObject;
  Vector3 offset = new Vector3(0.3f, 0.5f, 1f);
  // Start is called before the first frame update

  void OnTriggerEnter(Collider coll)
  {
      if (coll.gameObject.name != "Terrain")
      {
          if (Input.GetKeyDown(KeyCode.E))
          {
              Debug.Log("Clicked");
              GameObject pickUp = coll.gameObject;
              Debug.Log(coll.gameObject.name + " Has collided");
              pickUp.SetActive(true);
              coll.transform.position = camObject.transform.position + offset;
              coll.transform.parent = camObject.transform;
          }
      }
  }

OnTriggerEnter is only called once, when the collision happens.
You could try OnTriggerStay which is called almost all the frames for every Collider coll that is touching the trigger

You want to process input in Update only. Use OnTriggerEnter only to detect when entering the collider. You want something like this:

List<Collider> currentCollisions = new();

void Update() {
  if (Input.GetKeyDown(KeyCode.E)) {
    if (currentCollisions.Count > 0) {
      GameObject pickup = currentCollisions[0].gameObject;
      Debug.Log($"Picking up {pickup.name}");
    }
  }
}

void OnTriggerEnter(Collider other) {
  // Comparing object names is not good practice, so this should probably change.
  if (other.gameObject.name == "Terrain") return;

  currentCollisions.Add(other);
}

void OnTriggerExit(Collider other) {
  currentCollisions.Remove(other);
}
1 Like

Input.GetKeyDown is supposed to be used in Update. You might be able get away with using it in OnTriggerStay if your FixedUpdate rate is the same as your Update rate but that’s unlikely.

So maybe use Input.GetKey(KeyCode.E) in OnTriggerStay.

Keep in mind that if the object that entered the trigger is a rigidbody then it may fall asleep if not moving and stop triggering OnTriggerStay.

It’s not just unlikely, it’s pretty much impossible.

Input should only be handled in Update or LateUpdate. It should never be handled in physics callbacks like FixedUpdate, OnCollisionXXX, OnTriggerXXX as these will always have the problem of missing inputs.

Yeah in theory it could seem impossible but in practice it can work as I recently helped somebody else with a similar problem. After doing a little test I found that it did actually work when the Fixed Timestep was changed so that the FixedUpdate rate matched the Update rate. Although I still wouldn’t recommend doing it.

This isn’t possible because the Update rate is never fixed. Theoretically a maximum update rate can be set but never a minimum. There’s no way to guarantee a framerate in Unity.

It might have worked temporarily for you for a short time under ideal conditions. It won’t work in the real world on varying hardware etc.

Yeah I also didn’t feel confident that it would be reliable and so I didn’t recommend it.