Using OnControllerColliderHit and Instantiate to pick up objects but...

It creates more than one clone. Even though I instructed the character to destroy the item once hit. I assume it takes too long to destroy it so the script manages to instantiate twice before destroying. Can some explain why is that and what would be the fix? And some other optimisations for other things I’m doing in the script if you have the time. Here’s the code I use for the controller:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class OnCollisionEnterTest : MonoBehaviour {

    private void OnControllerColliderHit(ControllerColliderHit hit)
    {
        if (hit.gameObject.tag == "Gun")
        {
            Destroy(hit.gameObject);
            GameObject childObject = Instantiate(hit.gameObject) as GameObject;
            childObject.transform.parent = Camera.main.transform;  // Fix: multiple clones
            childObject.transform.localPosition = new Vector3(0.3f, -0.2f, 0.9f);
            childObject.transform.localRotation = Quaternion.Euler(0.0f, 0.0f, 0.0f);

        }
    }
}

Correct, destroy does not happen immediately, but rather around the end of the frame.

The correct way to fix it would be to add a class-scope boolean, such as ‘IsHit’. Set it to false in the Start() function, then in the collision function, only run your logic if it’s false, then set it to true. That will ensure the logic only gets called once.

You can try check the hit.gameObject before clone it, put a if(hit.gameobject)