I'd like to do the following:
void Update()
{
GameObject gob = Instantiate(Prefab);
MyContainer comp = gob.GetComponent<MyContainer>();
comp.SetName("something dynamic"); // We'll get an error here
}
The problem is, in the below class, SetName
is accessing an object that is only instantiated in Start(). Unity's order of events won't have MyContainer.Start()
called until the next frame (see example implementation below).
class MyContainer : MonoBehaviour
{
TextMeshProUGUI textObj;
void Start()
{
textObj = GetComponentInChildren<TextMeshProUGUI>();
}
void SetName(string name)
{
// Null Reference Here
textObj.text = name; // textObj isn't set yet;
}
}
Is there a recommended/sane way to go about dealing with objects in a scenario like this? I'd like to prevent too much boilerplate code in all my MonoBehaviour
subclasses while mainting a solid separation of concerns.
The options I've thought of thus far are:
Use flags:
a. OnEnable, if
name
is set, set the textb. On
SetName
, ifisActiveAndEnabled
, set the text- Change
SetName
to a coroutine and add ayield return null
statement at the top. - Similar to 2, use
Invoke
None of these seem ideal.
- 1 requires spaghetti-style state checks on every method.
- 2 requires the return values of methods to be
IEnumerator
even though nothing is actually intended to be returned. - 3 requires an extra, 0-argument method for each public method and extra state in the
MyContainer
class to store the arguments.