Hey everyone, I noticed that PlayCanvas does not support this.initialize() order, and will load in order of which entity was loaded first in the scene. I needed granular control over initalizations, so I wrote a wrapper function for this. Hope it is useful to you.
NOTE: You need the wrapper to kick off after all .initialize() have been run, so I kick it off using .postInitialize() and keep an instance on an entity in the scene. So you will need to create an entity in your scene and attach this to it as a script for it to work
NOTE: SomeScript.prototype.postInitialize will ONLY be called if that script also has SomeScript.prototype.initialize on it, so you cannot remove the empty “initialize” function
var InitQueue = pc.createScript('initQueue');
InitQueue.prototype.initialize = function(){
};
InitQueue.prototype.postInitialize = function() {
InitializationQueue.RunInitializations();
InitializationQueue.Finished = true;
};
// Force order of initializations
// We create an array of initialization functions
// In each script/s initializatoion that we need ordered, we call this "inits" object and add to it via InitalizationQueue.Add(sourceObj,index);
// Then we use InitHook which exists on an entity in the scene to run all these intializtions in order using its postInitialization function
// This means any ORDERED init that uses this InitializationQuee will happen after ALL other "regular" prototype.initializations are run
// Note that we check for undefined in case you assign inits[0] = something and inits[2] something leaving out init[1], it should still work
// Update: Added lists so that inits will stack if they have the same index,
// for example if you add 3 inits to index 0 and 4 inits to index 1, all 3 of index 0 will finish first but that is unordered
// it will skip any empty indices so don't worry about filling them; adding one script to [5] and one script to [6] will work as expected
//
var inits = []; // stores the whole source object, not just the "init" fn. Global var, whatever, sue me.
var InitializationQueue = {
RunInitializations : function (){
for(var i=0;i<inits.length;i++)
{
if (inits[i] !== undefined) {
for (var j=0;j<inits[i].length;j++){
inits[i][j].Init();
// console.log("intting:"+inits[i][j]);
// console.log("initting "+inits[i][j]+" on queue.");
}
}
}
},
Add : function(source,index){
if (this.Finished === true){
// console.log("initting:"+source+" because app already started.");
// The game already started, so just directly initiate it.
source.Init();
} else {
var i = parseInt(index);
if (i in inits === false) inits[i] = [];
inits[i].push(source);
}
},
Finished : false
};
usage:
// initialize code called once per entity
SomeScript.prototype.initialize = function() {
InitializationQueue.Add(this,3);
};
SomeScript.prototype.Init = function(){
// order dependent code here
};
// initialize code called once per entity
AnotherScript.prototype.initialize = function() {
InitializationQueue.Add(this,0);
};
AnotherScript.prototype.Init = function(){
// order dependent code here
};
in this example AnotherScript will have its Init function called before SomeScript
Also note that if you clone an entity with a script on it calling InitializaitonQueue at run time, it will notice InitializationQueue.Finished == true and initialize immediately as expected