0
\$\begingroup\$

I have two GameObjects and would like both to have a reference to the other. I know this can be done by creating public properties and setting them with Unity's inspector, but my preference is to stay in code whenever possible. Something like this:

public class Object1 : MonoBehavior
{
    private Object2 _object2;

    public void Start()
    {
        _object2 = GetComponent<Object2>();
    }
}

public class Object2 : MonoBehavior
{
    private Object1 _object1;

    public void Start()
    {
        _object1 = GetComponent<Object1>();
    }
}

I understand this doesn't work because one Start has to run before the other, but I'm not sure what alternative would be the best from a code quality standpoint.

  • I could refactor so Object2 doesn't have a reference to Object1, but then it can't call any functions on Object1. Instead, Object1 would have to constantly query Object2 for whether or not it should do something.
  • I could get the other component in Update rather than Start, but that seems like a bad strategy from a performance standpoint - searching for an object every frame even though it's always the same object.
  • I could solve it outside of Start / Update. For example, Object2 could have a SetObject1 function that Object1 calls, or an EventManager could be used to communicate between objects. This seems like it might be a tad overkill for something as commonplace as this.

Are any of these a common practice among Unity devs? Is there another option I'm missing?

\$\endgroup\$
3
  • \$\begingroup\$ Are you sure your code doesn't run? There shouldn't be a problem for calling both at the start. But you can add a while (_object1 == null) before _object1 = GetComponent<Object1>(); \$\endgroup\$
    – Arian_ki
    Mar 27, 2022 at 22:14
  • \$\begingroup\$ And another thing, what object1 is? the name says it's a game object but the code says it's a component \$\endgroup\$
    – Arian_ki
    Mar 27, 2022 at 22:15
  • \$\begingroup\$ Thanks for the response. It looks like the code does indeed run now - I screwed up elsewhere producing the null references and assumed this pair of Starts was the culprit. \$\endgroup\$ Mar 27, 2022 at 23:42

1 Answer 1

2
\$\begingroup\$

I understand this doesn't work because one Start has to run before the other.

No, it does work. Even if the two Start() functions execute one after another, the Components they are referencing already exist. You can test it for yourself by adding Debug.Log(_objectX) after using GetComponent<>().

Object1 would have to constantly query Object2 for whether or not it should do something.

This is called polling and it's perfectly fine, especially if you want to decrease interdependence among your classes and entities. Alternatively, you can expose some events and invoke callbacks accordingly.

I could get the other component in Update but that seems like a bad strategy.

Yes, it is.

I could solve it outside of Start / Update.

Unity encourages using Awake() for script referencing rather than Start(). This way, when Start() executes, all your scripts own a working reference regardless of their execution order.

An EventManager could be used to communicate between objects.

It would also help you avoid mutual references among objects. The EventManager may expose UnityEvents that trigger ObjectX's callbacks when needed.

\$\endgroup\$
1
  • \$\begingroup\$ Oh, you're right. I made a mistake elsewhere and misinterpreted the problem. Thanks for that + all this other information. I'll be sure to use Awake from here on. \$\endgroup\$ Mar 27, 2022 at 23:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .