• Hey! Guest! The 40th (!!!) GMC Jam will take place between February 25th, 12:00 UTC to March 1st 12:00 UTC. Why not join in this very special anniversary jam! Click here to find out more!

GMS 2.3+ Change execution order of script assets

Agneum

Member
Is there a way to to make sure one script asset runs before the other? I've tried dragging the script to the top , but that didn't seem to change anything (not to mention there is no easy way to order sort scripts anyways).

The blog post reads:
"scripts are no longer called individually, but are actually all run at the start of the game in the global scope".
 

Agneum

Member
Move the content of the second script into the first script and then delete the second script.
This would be a work-around, but I don't like the idea of merging two separate function files together just because there is a dependency between them. From what it seems, the order of execution seems to be based on on the asset name itself. Would much prefer to have them execute in the order they appear in the tree, or for us to be able to set a priority in the asset browser.


In my case, I run tests at the bottom of each script on a conditional global variable. This would force me to put all tests in the settings script. Which would put the tests in an illogical script, and also bunch them into an incohesive mess.

That or I guess I need to initialize everything using a timer..
 

FrostyCat

Member
Wrap each of the scripts in a function wrapper, then create another script calling them in sequence, thereby specifying the order.
GML:
function initA() {
    ...
}
GML:
function initB() {
    ...
}
GML:
initA();
initB();
 

FrostyCat

Member
Open the yyp and move the script you want to run first to the top of the yyp and save it. *undocumented*
Undocumented as of GMS 2.2, and defective as of GMS 2.3.

You need to stop dispensing this "undocumented ID order" advice right now, as well as its variants like your beloved "resource ID plus offset" hack.
 
Wrap each of the scripts in a function wrapper, then create another script calling them in sequence, thereby specifying the order.
After reading about the changes to scripts and functions, I believe the approach offered by FrostyCat is the most practical way to handle setting a specific order for your scripts/functions now.

Agneum, I'm not sure if this analogy is entirely accurate, but from what I'm gathering in the release notes it seems like they've turned scripts into something like a Class in other programming languages and we can now use them to organize several related functions. For example, I created a new script in my game and called it "Utility." Then I converted several of my helper scripts into functions and added those new functions (ex: "fn_initialize_array", "fn_create_obstacle", etc.) to the newly created "Utility" script so they're all in one place now. I don't know the details of your specific scenario but maybe this idea of "Class" organization could help you keep your scripts organized in this new environment and avoid the "incohesive mess" you were concerned about?
 

samspade

Member
Wrap each of the scripts in a function wrapper, then create another script calling them in sequence, thereby specifying the order.
GML:
function initA() {
    ...
}
GML:
function initB() {
    ...
}
GML:
initA();
initB();
I'm working through this exact issue right now, and I might be missing something, but I don't think this works. If you're declaring these script functions in separate script assets, you have the same issue the order they are run in matters. But the bigger issue is even if the first thing did work, it doesn't give you the same results. Script functions initialized purely inside a script asset are global and unbound. Script functions initialized inside a script function inside a script asset are not. For example the following code will give you an error: Variable <unknown_object>.increase_my_variable(100007, -2147483648) not set before reading it.

GML:
///script asset

function init_func() {

    function increase_my_variable() {
        my_variable += 10;
        show_debug_message(my_variable);
    }

}

init_func();

///object
my_variable = 50;
increase_my_variable();
I could be wrong but I really think there is no way to enforce a specific order of script assets.
 

FrostyCat

Member
I'm working through this exact issue right now, and I might be missing something, but I don't think this works. If you're declaring these script functions in separate script assets, you have the same issue the order they are run in matters. But the bigger issue is even if the first thing did work, it doesn't give you the same results. Script functions initialized purely inside a script asset are global and unbound. Script functions initialized inside a script function inside a script asset are not. For example the following code will give you an error: Variable <unknown_object>.increase_my_variable(100007, -2147483648) not set before reading it.

GML:
///script asset

function init_func() {

    function increase_my_variable() {
        my_variable += 10;
        show_debug_message(my_variable);
    }

}

init_func();

///object
my_variable = 50;
increase_my_variable();
I could be wrong but I really think there is no way to enforce a specific order of script assets.
Your code is wrong. The inner function declaration is accessible only to code inside the outer function, it is not magically transferred to instances that run the outer function.
 

samspade

Member
Your code is wrong. The inner function declaration is accessible only to code inside the outer function, it is not magically transferred to instances that run the outer function.
Wrap each of the scripts in a function wrapper, then create another script calling them in sequence, thereby specifying the order.

Maybe I'm confused then, because I thought I was copying your example. What was it supposed to be?

As a side note, it does appear to be creating them in the scope that it is running as that same code in an instance creates an inner function usable by the instance (with access to the instance's variables) and the code as posted will run without errors if you prefix global before variables in the instance e.g.

GML:
global.my_variable = 50;
global.increase_my_variable();
produces no errors, indicating a named function bound to global scope has been created.
 

FrostyCat

Member
Maybe I'm confused then, because I thought I was copying your example. What was it supposed to be?
You completely took my example out of context.

Assume that foo must be initialized before bar. My suggestion is that the two initializations be placed in their own functions, then called in a third script that runs on startup.
GML:
function init_foo() {
    /* Initialize foo */
}
GML:
function init_bar() {
    /* Initialize bar */
}
GML:
init_foo();
init_bar();
As a side note, it does appear to be creating them in the scope that it is running as that same code in an instance creates an inner function usable by the instance (with access to the instance's variables) and the code as posted will run without errors if you prefix global before variables in the instance e.g.

GML:
global.my_variable = 50;
global.increase_my_variable();
produces no errors, indicating a named function bound to global scope has been created.
That's a direct consequence of the global scope binding phenomenon you observed earlier on. I may have mis-predicted the actual accessibility of increase_my_variable, but that still doesn't make your example right.

Script functions declared at the global level have no built-in self, but get that identity whenever it is called. Methods carry their own self, and work off that bound identity no matter where it is taken. Your increase_my_variable is an example of the first kind by the virtue of it being declared using the named function syntax.

This is why I do not use the named function syntax (i.e. function NAME(...) { ... }) for anything other than declaring script functions at the top level. Everything else I use the anonymous syntax (i.e. NAME = function(...) { ... }).
 
Top