When programming your game using GML you should be aware
that function call arguments are not guaranteed an evaluation
order. What this means is that the order in which you place
functions in your code will change from platform to platform, so
you should code them in an explicit manner. This is due to
optimisation differences between the different target platforms,
for example on the Windows target functions may be evaluated from
right to left, but on the HTML5 target, they may be evaluated from
left to right. So to avoid any issues you are best not to call
multiple functions in the arguments of a function call as you may
well be building in a reliance on the order of evaluation.
To see an example of what this means, consider the following code
which is calling several functions and using them as arguments to a
script:
buffer_seek(buff, buffer_seek_start, 0);
scr_buffer_get_info(buffer_read(buff, buffer_s8), buffer_read(buff,
buffer_s16),buffer_read(buff, buffer_s16));
Now, the problem here is that on some platforms, the last
buffer_read will be called first, and so all the
arguments of the script will be wrong as the data is being read
from the buffer in "reverse" order as you would perceive it. This
has the knock-on effect here of affecting all further values for
the buffer_read function so all the arguments being passed
to this script will be wrong!
To get around this you should explicitly call the functions
in the required order and store the returned values in variables,
like this:
var val[0] = buffer_read(buff, buffer_s8);
var val[1] = buffer_read(buff, buffer_s16);
var val[2] = buffer_read(buff, buffer_s16);
scr_buffer_get_info(val[0], val[1], val[2]);
While it may seem a more verbose method, it keeps everything clear
and avoids any possible problems with evaluation order.
You should also take care when using expressions too, as the order
in which they are evaluated in will change depending on which
target you are compiling to. So, when using expressions in your
code, ensure you use brackets () to properly control the order of
operations. This is very important to ensure the correct behaviour
of your games across all the target platforms games and is
essential for JavaScript platforms. For example, consider
the following code:
a = b == c || d;
The different target compilers will perform the operations in
different orders since they are not explicitly shown, giving rise
to "odd" results that you may not expect when you play your game.
To avoid this, use the () to separate out the parts, like this:
a = (b == c || d); //better
a = ((b == c) || d); //best