Script Loading Order

Continuing the discussion from PlayCanvas Editor Feedback:

Is your problem the order of script loading? The order of script loading has changed with this update. Previously we would order loading based on the order the scripts appear in the hierarchy. Now we load all scripts in a repository, so we don’t use the hierarchy order. Instead we’ve added a way to set the loading priority of your scripts.

In the main menu (click the PlayCanvas logo in the top left) select “Script Priority”. You can use this dialog to set some or all your scripts to load in a specified order.

Usually for playcanvas style scripts the order doesn’t matter but if you need to specify some scripts to load first, you should add them to this list.

Hope that solves the problem.

Brilliant! - looks like lmao was having the same problem

One slight problem with that

I have too many scripts and they don’t all fit on the screen :frowning:!!! Having a bit of a problem selecting the one I need which is off the top!

OK. We can fix that. :smile:

Do you need to specify the exact loading order for all your scripts? Or is it possible just to include a few in the priority loading?

Note this list doesn’t effect “execution” order.

It’s ok, rotating my monitor worked around it this time :smile:

I just need the key libraries I use loaded before any pc.script.create calls - a couple I’ve written and d3, lodash etc. I just couldn’t get to a couple in the normal monitor orientation!

Working now though.

I’ve just deployed an update to the script selection. We now use the standard asset picker to select scripts. This should fix the problems when there are too many scripts to select.

I don’t see Script Loading Order option in PlayCanvas menu. Am I missing something?

Update: Found it. The option has moved. click any script (so the script itself is selected, not entity), then on the inspector pane there is an option to change loading order.

You can also get to that by clicking on the settings icon in the bottom left of the screen (the gears like icon)

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

2 Likes