Optimisation Tip: Use a dictionary of colliders to access components, not GetComponent

If you are doing this any significant number of times in a frame:

    private void OnCollisionXXX(Collision collision)
    {
        MyClass iNeedToKnowThisInfo = collision.collider.GetComponent<MyClass>();
    }

or using Physics.OverlapXXX() to gather a list of colliders and doing the same, consider doing this instead:

public class Presence
{
    public static Dictionary<Collider, Presence> lookUp = new Dictionary<Collider, Presence>();

    public MyClass goshImQuickToAccess;
    public MyOtherClass iAmAlsoQuickToAccess;

    public Presence(Collider c)
    {
        lookUp[c] = this;
    }
}

public class MyClass : MonoBehaviour
{
    public Collider myCollider;
    public Presence myPresence;

    void Start()
    {
        myPresence = new Presence(myCollider);
        myPresence.goshImQuickToAccess = this;
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (Presence.lookUp.TryGetValue(collision.collider, out Presence p))
        {
            if (p.goshImQuickToAccess) DoSomething(p.goshImQuickToAccess);
            if (p.iAmAlsoQuickToAccess) DoSomethingElse(p.iAmAlsoQuickToAccess);
        }
    }
}

In testing, the dictionary lookup is between 10-15 times faster than GetComponent, and it gives you access to as many components (or other data) as you care to back-reference from Presence.

Happy colliding!

EDIT: It would be really nice if the Collider class could have a generic metadata field - an ‘object’ that could hold a reference to whatever the user wanted, eliminating the need for a dictionary lookup.

1 Like

Nice contribution! A couple of notes though:

  • Use OnEnable() / OnDisable() instead of Start(). They’re much more consistent with the component lifecycle.
  • Add some procedure to remove the class from the dictionary. Use OnDisable() for that.

That would support components being enabled / disabled / instantiated / destroyed / hot script reload, etc.

1 Like