is there a monobehaviour method guaranteed to get called before I can call getter / setters for custom properties?

Basically, I have a script that goes along the lines of:

public class EdgeCasting : MonoBehaviour {

private LineRenderer edgeRenderer;
private Vector3 _edgeOrigin;
private bool nextNodeCreationInProgress = false;

public Vector3 edgeOrigin {
	get {
		return _edgeOrigin;
	}
	
	set {
		_edgeOrigin = value;
		edgeRenderer.SetPosition(0, _edgeOrigin);
	}
}

void Start() {
	edgeRenderer =  transform.Find("Edge").GetComponent();
}

    ...

I noticed that if (from another object) I instantiate the prefab to which this script is attached and then try to set the edgeOrigin property, like so:

newEdge = (EdgeCasting)((GameObject)Instantiate(Resources.Load("Edge"), transform.position, Quaternion.identity)).GetComponent<EdgeCasting>();
newEdge.edgeOrigin = transform.position;

newEdge’s edgeRenderer is not yet initialized / assigned by the time I try to set it indirectly thru the edgeOrigin property.
I assumed Start() was a sort of monobehaviour “constructor” if you will and so it was guaranteed to be called before one was able to manipulate a script instance. I guess I was wrong. So, is there any way to make sure any private members are initialized before being able to start accessing properties in the script / class? I mean other than making the renderer a public property and manually assigning it before using edgeOrigin.

If your LineRenderer is part of your prefab, you can make your edgeRenderer variable public (or add the SerializeField attribute) and link the LineRenderer in the inspector. That way the variable is set automatically when the object is Instantiated.

1 Answer

1

You need to use Awake() as if it were a parameterless constructor.

Note that Awake does not run on Prefabs until they are instantiated, but you can call functions on your scripts on Prefabs (a generally bad idea unless you have some specific purpose in mind).

right, my guess was that Awake or Start would be "sort of" constructors.However, you say that Awake() does not get called on prefabs but at least through Resources.Instantiate() both Awake() and Start() are being called for each instantiation. Still, like my question states, if I instantiate and try to set the edgeOrigin property, the renderer is still null.. Like, my call to the accessor seems to happen immediately before Awake() and Start(). If after the first Update() I try to re-access or set the property, then the renderer is already set.

Awake is called before the Instantiate method returns. Start is called the next frame before Update. So Awake is called before you have the chance to access your properties unless you access them from the class constructor itself...

@Bunny83 yes I just tested this out myself, If in my above code I move the initialization of the renderer from Start() to Awake() it does work just fine. Now, why did @whydoidoit say Awake() is not run on prefabs? Like I said, it DOES run on a prefab instantiated through Instantiate()

Don't mixup Prafabs with instances of Prefabs ;) This is like a picture of a car can't drive, a real car can ;)

Oh ok so he just meant it doesn't get called on the prefab itself. Like "Awake()" is not a class method but rather an instance method.