Is there any way to specify the order that Awake and/or Start are called? If not, is there any “nice” way to implement some sort of LateStart procedure (i.e. something that is called after all Starts have been called, but before any Updates)?
I would like something to happen in between having all my GameObjects initialized and the first Update. At the moment, the only way I can think of achieving this is by essentially circumventing the features of Unity and just implementing a usable version of MonoBehaviour myself.
No, you cannot order nor predict the order all of the Awake()s or Start()s are fired, but what I do is have a GameManager instance variable that I call something like readyToStart that is a boolean.
Then inside my Start()s I have…
function Start() {
// all my setup code here
//
// to here
while(!GameManager.readyToStart)
yield;
// do rest of my setup here
}
Then if I dont want my Update() to fire yet I can just do this…
function Update() {
if (GameManager.readyToStart) {
// do my update look stuff
}
}
Then one of my scripts that manages my game logic will set readyToStart = true when I know I have everything in place (so to speak).
Your solution would certainly work in non-complex cases, but I have a couple of issues with that method:
What happens if the scene’s “readyToStart”-ness is dependent on more than one object?
Example: Say you had 3 objects, X, Y, and Z, that need to be initialized in that order (because Y depends on X, and Z depends on Y). Y would have to wait on an xInitialized flag and Z would have to wait on a yInitialized flag. This could easily grow out of control, especially if multiple objects were waiting on multiple other objects.
Having a flag check in every Update call of every MonoBehaviour seems unnecessarily inefficient, and it would be tedious to have to remember to put the check in for every new object you create.
My situation is this:
I have been using the publisher/subscriber pattern with a central Broker object (MonoBhvr) that allows objects to subscribe to events, and publish those events.
Since I can’t specify the order of Awake, no objects can attempt to subscribe to the Broker in Awake, so they have to do that in Start. However, since I can’t specify the order of Starts, an object can’t Publish anything in Start since some other objects may not be subscribed yet.
I want to publish a GameStart event from my GameManager object so that many objects can initialize themselves using paramaters determined during the GameManager’s initialization. This means that the GameManager is depending on all other objects to have finished their Start method before it can publish. Also, I don’t particularly want any objects to go through an Update cycle before they have received the GameStart event (as they won’t be properly initialized).
Surely there must be a solution that doesn’t involve changing every Update function?
(Sorry if this is coming off as rant-ish. I’m just quite frustrated that what should be a simple task is requiring so much work.)
Why not have .enabled == false for the majority of your script components as the initial state, and only when you are ready you go through and enable them? Should remove the inefficiency, and nothing much will happen until you flick the switch.
Well that’s certainly a better solution. I think I’ll go with that, although I really wish there was a more appropriate way to do this.
Ideally we’d have scripts attached to the scenes themselves that would have some Initialization and Cleanup method so that you could have some well-ordered code that runs at the start and end of each scene.[/code]
Couldn’t you simply have your initialization all occur in a single script, thus assuring the order you need? That “main” script could establish references to all of the other objects/scripts you need to initialize, either on the fly or via Unity’s inspector.
In my first app I actually had almost every single thing that happens exist in a single script with maybe a couple dozen functions (some quite elaborate) but only one Awake() function to set up everything.
Well this is what I mean by “circumventing” Unity’s features. What’s the point of using a MonoBehaviour if you’re just going to do the initialization calls yourself? What happens if you need Updates to be a particular order (and LateUpdate does not suffice)? Then you have to write your own Update call.
I’m quite capable and fine with doing that, but it’s frustrating that you have to hack your way around Unity’s default behaviour just to get things working in a usable fashion.
But it is the only way and really the simplest as you just could add an empty game object to the scene, a manager object, to which you apply a component with a public array.
Then in the update function of that component, you can do the order dependent updates, while the distinct objects still can do the independent update code.
Thats a pretty well designed code and actually easy to maintain and manage.
Thats also not hack around but one of the great powers of unity. “manage what needs management, let the rest run on its own”
You will always require this kind of things.
How would you do performant “group AI” without some kind of management object.
Or network management and matchmaking, as well as GUI for example benefitsfrom dedicated game objects which you can globally enable and disable.
I used update as a replacement for any kind of the common function you might need.
My problem with it is that it that you essentially have two mechanisms for doing the same thing, which can introduce confusion when a new programmer joins the team.
For example, they add an object to the scene. They go to the script to write the initialization code, which they will assume is done in the Start method, because that’s Unity’s way of handling post-construction initialization. Of course, if you’ve written your own Manager class that needs references to all objects, then this is going to introduce issues.
Your group AI analogy doesn’t really equate because Unity doesn’t pretend to handle AI, so there is no confusion over what mechanisms to use.
I’m not saying it’s not possible, but I’m really not a big fan of having two systems in place that do essentially the same thing.
You are right, Unity does not pretend to handle AI
But I guess your game will require some kind of AI as well and in different cases the very case I just mentioned will be an important topic to solve.
The moment more than 1 AI opponent is present, you are basically in the situation where team logic might be required for temporal teaming against an enemy (be it only a non-attacking behavior against a specific enemy).
But basically this problem is a no problem.
Thats the very job of documentations to handle.
Also manager classes are a basic requirement for any kind of simulation. Independent of the technology.
Unity just makes it seem like it isn’t required, but working around a manager commonly wastes masses of CPU time as all instances redo the very same work that the manager could do in one go