- Home /
Instantation and use of gameobject in same frame
Hi,
I would like to know how you deal with a scenario like this:
When a mouse button is clicked a prefab is instantiated.
This prefab have some components that need initialization and the initialization code is placed in awake and start.
Right after creation (same frame) the gameobjects are passed to a function that will do some calculatiosn with it.
You see the problem. The initialization hasn't been ran for the different components in the game object. So, 3 won't work or will render a wrong result.
Solutions I have found (thought about):
After creation wait for next frame with a coroutine (WaitForEndOfFrame) and then, execute step 3(pass this objects now that awake and start has been called to the worker function).
Instantiate the game object and them add it to a list. After all frame work is done when LateUpdate() callback of the behaviour that created the gameobject is called, test if there are newly created gameobjects and pass all these newly created objects to the worker function.
Move initialization code to different inits in each behavour and initialize then manually (really bad aproach).
Would you mind commenting any other way to accomplish this?
Cheers.
Not 100% sure, but I believe Awake is called as part of Instantiate. So anything initialised there will be available for your next line of code. Worth double checking this.
Start will not run until before Update starts in the next frame, so is not overly helpful to you.
You are totally right. Didn't know how I could miss this. Awake is called through the instantiation process.
Answer by Kiwasi · Nov 24, 2014 at 08:55 AM
Just ran a quick test in Unity to confirm. Awake is called before the next line of code, so long as the prefab is an active GameObject.
Here are the scripts and the results.
public class FunctionTestManager : MonoBehaviour {
public GameObject testPrefab;
void Start () {
Debug.Log ("Before Instantiate");
Instantiate (testPrefab);
Debug.Log ("After Instantiate");
}
}
public class FunctionTest : MonoBehaviour {
void Awake (){
Debug.Log ("Awake");
}
void Start () {
Debug.Log ("Start");
}
}
Console reads
Before Instantiate
Awake
After Instantiate
Start
Accepted this as OP has indicated this worked in comments.
Answer by AlwaysSunny · Nov 24, 2014 at 12:15 AM
This type of open-ended question is better suited to the forums.
If you can wait till next frame to use the object and let start/awake handle initialization, I guess that's fine. I personally prefer custom Inits to all that rigamarole. It really varies case by case which is more appropriate, but I find Inits much cleaner. If you inherit from a base class and override a virtual (blank) Init, you don't even need to have the script object as its derivative type. I have manual Inits in about a quarter or third of my scripts. They're not that bad to work with.
One of the things I don't like about the multi init thing is that retrieving a component is an expensive operation. Doing this, components would need to be requested x2. One pass when you manually have to do manual initialization and another one when unity needs to get them to set values, etc... It feels a bit dirty to me. And if I would have to do this I would create an "Entity Controller" that would be the one that now what components to init and how. For me, this smells like good old inheritance based initialization more than component based system initialization. Could be wrong though.
You're right that it's going to create some waste and some spaghetti. I've not found a better way, though. Each project I work on gets a highly generic inherit-from-me class that includes lazy-getters for project-specific components to ease some of the burden. That's more for dev convenience than performance, though.
Also I'm sure you're aware that if you need to get a component twice in the same scope, you can store a scope-level reference and use GetComponent only once. I assume the garbage that creates is superior to the waste of two GetComponent calls.
After some test (Unity was not compiling my scripts) seems that awake is called in the Instantiate process as Bored$$anonymous$$ormon suggested. This is all I need :).