<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"><head>
<script type="text/javascript" language="JavaScript">
//<![CDATA[
function reDo() {
if (innerWidth != origWidth || innerHeight != origHeight)
location.reload();
}
if ((parseInt(navigator.appVersion) == 4) && (navigator.appName == "Netscape")) {
origWidth = innerWidth;
origHeight = innerHeight;
onresize = reDo;
}
onerror = null;
//]]>
</script>
<style type="text/css">/*<![CDATA[*/
< !-- div.WebHelpPopupMenu {
position: absolute;
left: 0px;
top: 0px;
z-index: 4;
visibility: hidden;
}
p.WebHelpNavBar {
text-align: right;
}
-->
/*]]>*/</style>
<script type="text/javascript">//<![CDATA[
gRootRelPath = "../..";
gCommonRootRelPath = "../..";
gTopicId = "9.1.1_8";
//]]></script>
<script type="text/javascript" src="../../template/scripts/rh.min.js"></script>
<script type="text/javascript" src="../../template/scripts/common.min.js"></script>
<script type="text/javascript" src="../../template/scripts/topic.min.js"></script>
<script type="text/javascript" src="../../template/scripts/topicwidgets.min.js"></script>
<script type="text/javascript" src="../../whxdata/projectsettings.js"></script>
<link rel="stylesheet" type="text/css" href="../../template/styles/topic.min.css"/>
<link rel="stylesheet" type="text/css" href="../../template/Charcoal_Grey/topicheader.css"/>
<meta name="topic-status" content="Draft"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<title>Script Functions And Variables</title>
<meta name="generator" content="Adobe RoboHelp 2019"/>
<link rel="stylesheet" href="../../assets/css/default.css" type="text/css"/>
<meta name="rh-authors" content="Mark Alexander"/>
<meta name="topic-comment" content="Page outlining the use of scripts to create functions and global variables and macros"/>
<meta name="rh-index-keywords" content="Script Functions And Variables"/>
<meta name="search-keywords" content="user defined functions,script functions,gmcallback_,gmcallback"/>
</head>
<body>
<div class="topic-header rh-hide" id="rh-topic-header" onclick="rh._.goToFullLayout()">
<div class="logo">
</div>
<div class="nav">
<div class="title" title="Script Functions And Variables">
<span>Script Functions And Variables</span>
</div>
<div class="gotohome" title="Click here to see this page in full context">
<span>Click here to see this page in full context</span>
</div>
</div>
</div>
<div class="topic-header-shadow rh-hide" id="rh-topic-header-shadow"></div>
<!--<div class="body-scroll" style="top: 150px;">-->
<h1>Script Functions And Variables</h1>
<p>Script assets are essentially a collection of one or more user defined functions or variables that you write yourself as short snippets of code in the <a href="../../The_Asset_Editors/Scripts.htm">Script Editor</a>. The functions you define in a script
can resolve expressions, return values or do anything else that the GameMaker Language permits, just like the built in <a href="Runtime_Functions.htm">runtime functions</a>.</p>
<p>Script functions should generally be used if you have a block of code that you use in more than one place or object, or when you want a block of code to be used across multiple objects in a modular fashion. Using scripts to define functions means that
you can change the function just once when required and the change will be "picked up" by every object that has a call to the function.</p>
<p>Scripts can also be very handy from an organizational point of view, as they permit you to create groups of functions that all work within the same namespace - for example, you might have several functions all related to collisions between instances
in your game, so you would create a "<span class="inline">Collision_Functions</span>" script and store all these functions together in it.</p>
<p>When creating a script with functions in it, the functions must be created using the following formats:</p>
<p class="code"><span>function <name>( <parameter1>, <parameter2>, etc... )</span><br/>
<span> {</span><br/>
<span> <statement1>;</span><br/>
<span> <statement1>;</span><br/>
<span> ...</span><br/>
<span> }</span></p>
<p>or:</p>
<p class="code"><span><span><name> = </span>function( <parameter1>, <parameter2>, etc... )</span><br/>
<span> {</span><br/>
<span> <statement1>;</span><br/>
<span> <statement1>;</span><br/>
<span> ...</span><br/>
<span> }</span></p>
<p>In general, however, you would use the <em>first </em>form for script functions as it will define the function as specifically being a script function, meaning that it will be <strong>global </strong>in <a href="Variables_And_Variable_Scope.htm">scope</a>,
be assigned a <strong>script index</strong>, and not require the <span class="inline">global</span> prefix to identify it since the compiler will recognise it as a script function. Using the second form will instead be generating a global scope
<a href="Method_Variables.htm">method variable</a>, and as such it will <em>not </em>be recognised as a script function by the IDE and will require the use of the <span class="inline">global</span> prefix when being referenced in your code.</p>
<p class="note"><strong>NOTE</strong>: You can check this by using both forms in a script and then calling the runtime function <a href="../GML_Reference/Variable_Functions/typeof.htm">typeof()</a> on each of them. One will be classed as a "number" - since
it returns a script index ID - and the other will be classed as a "method".</p>
<p>We also recommend that you add comments to define the properties of the function (see the section on <a href="../../The_Asset_Editors/Code_Editor_Properties/JSDoc_Script_Comments.htm">JSDoc Comments</a> for more details), such that a simple script would
look like this:</p>
<p class="code">/// @function log(message);<br/> /// @param {string} message The message to show<br/> /// @description Show a message whenever the function is called.<br/>
<br/> function log(message)<br/> {
<br/> show_debug_message(message);
<br/> }
</p>
<p>Additional functions for the script can be added using the same format as shown above, one after the other within the script asset.</p>
<p><img alt="Multiple Functions In One Script" class="center" src="../../assets/Images/Scripting_Reference/GML/Overview/Multiple_Functions_Scripts.png"/>Functions in scripts can also return a value, just as runtime functions can, and as such they can
be used in expressions. For this you would use the <a href="Language_Features/return.htm"><tt>return</tt></a> statement:</p>
<p class="code">return <expression></p>
<p>It should be noted that the <strong><i>execution of the function ends at the return statement</i></strong>, meaning that any code which comes after the return has been called <i>will not be run</i>. Here is a short example function from a script called
"<span class="inline">sqr_calc</span>" which calculates the square of whatever value is passed to it, and it includes error catching in case the parameter that it is passed is not a real number:</p>
<p class="code">/// @function sqr_calc(val);<br/> /// @param {real} val The value to calculate the square of<br/> /// @description Calculate the square of the given value<br/>
<br/> function sqr_calc(value)<br/> {
<br/> if !is_real(value)<br/> {
<br/> return 0;<br/> }
<br/> else
<br/> {
<br/> return (value * value);<br/> }
<br/> }
</p>
<p>Note that if you create a script function with <em>no</em> return value then in your code check for one, you will get the value <span class="inline">undefined</span> by default.</p>
<p>To call a script function from within a piece of code, just use it the same way as when calling any runtime function - that is, write the function name with the parameter values in parentheses. So, the above script would be called like this:</p>
<p class="code">if keyboard_check_pressed(vk_enter)<br/> {
<br/> val = scr_sqr(amount);<br/> }
</p>
<p class="note"><strong>NOTE</strong>: When using your own functions from scripts in the code editor, you can press<span> <img alt="F1 Icon" class="icon" height="20" src="../../assets/Images/Icons/Icon_f1.png" width="55"/></span> or click the middle mouse button <span><img alt="MMB Icon" class="icon" src="../../assets/Images/Icons/Icon_MMB.png"/> </span>on
the function name to open the script that contains it for editing directly.</p>
<p>It is important to understand that script <i>names</i> are <b>independent of the functions that they contain</b>, so you can name your scripts in a more "common sense" way, ie: all your AI functions could go in a script "<span class="inline">Enemy_AI</span>"
(following the standard asset naming conventions of alpha-numeric characters and the underbar "_" only). However, you can still call scripts in your game - and you can name scripts the same as a function that you define in them - which can
give rise to a issues due to the way that GameMaker Studio 2 stores asset references. To give an example consider this code, called from an instance:</p>
<p class="code">function indirectCall(func, arg)<br/> {
<br/> func(arg);
<br/> }
<br/> indirectCall(myscript, arg);</p>
<p>The above code is attempting to call a script called "myscript" within a method, which in this case will fail. This is because the in-line function is actually using the <em>index</em> for the script asset and <strong>not </strong>actually
calling the script - eg: if the script index resolves to "4", essentially the function is calling <tt>4(arg);</tt>, which makes no sense. The code should instead be structured in one of the following two ways:</p>
<p class="code">function indirectCall(func, arg)<br/> {
<br/> func(arg);
<br/> }
<br/> indirectCall(method(undefined, myscript), arg);<br/>
<br/> // OR<br/>
<br/> function indirectCall(func, arg)<br/> {
<br/> script_execute( func, arg);<br/> }
<br/> indirectCall(myscript, arg);</p>
<p>This is important to note, especially when working with legacy projects where scripts contain one single function, and the function is named the same as the scrpt. However, you really should <em>never</em> do this, and your scripts should be named independatly
of the functions they contain.</p>
<p>This leads us to the final and most important thing to know about scripts and the functions they contain: scripts are parsed on a <b>global</b> level and will be <strong>compiled at the very start of the game</strong>. This means that <em>technically</em> all functions in a script are "unbound" <a href="Method_Variables.htm">method variables</a>, and any variables declared outside of a function in the script will be considered <a href="Variables/Global_Variables.htm">global variables</a>.
For example, consider this script:</p>
<p class="code">function Foo()<br/> {
<br/> // Do something<br/> }
<br/> blah = 10;<br/> function Bar()<br/> {
<br/> // Do something else<br/> }
</p>
<p>In the above case, not only have we defined the functions <tt>Foo</tt> and <tt>Bar</tt> but also the variable <tt>blah</tt> and all of them are considered to have been created in the <b>global</b> scope. The functions don't need the <tt>global</tt> keyword to be recognized as the compiler understands that these functions are part of the script, but if you wanted to access <tt>blah</tt> then you would need to do:</p>
<p class="code">val = global.blah;</p>
<p>That said, we recommend that you <b>always explicitly type global variables</b> when creating them in scripts to prevent any issues later. Scripts are also an ideal place to define any <strong>Macros</strong> or <strong>Enums</strong> (<a href="Variables/Constants.htm">constants</a>),
as adding them to a script outside of a function also means that they will be created for use before the game code actually starts running. Below is an example of a script that is creating different global scope values for a game:</p>
<p class="code">/// Initialise All Global Scope Values And Constants<br/> global.player_score = 0;<br/> global.player_hp = 100;<br/> global.pause = false;<br/> global.music = true;<br/> global.sound = true;<br/>
<br/> enum rainbowcolors {<br/> red,<br/> orange,<br/> yellow,<br/> green,<br/> blue,<br/> indigo,<br/> violet<br/> }<br/>
<br/> #macro weapon_num 3<br/> #macro weapon_gun 0<br/> #macro weapon_bomb 1<br/> #macro weapon_knife 2</p>
<p>Note how all these constants are set up outside of any function call, meaning they will be initialised before everything else and at a <em>global </em>scope. This means that if you want to use a script to initialise variables on an <em>instance </em>scope
then you must wrap them in a function, for example:</p>
<p class="code">/// @function init_enemy();<br/> /// @description Initialise enemy instance vars<br/>
<br/> function init_enemy()<br/> {
<br/> hp = 100;<br/> dmg = 5;<br/> mana = 50;<br/> }
</p>
<p>So, scripts can be used to generate macros, enums and global variables before the game starts so they are ready for use at any time, and they can also be used to create "unbound" methods (user-defined functions) that can be used in your game
like GML runtime functions.</p>
<p>One final thing to note about script functions is that if you are developing for <strong>Web </strong>(ie: targeting <strong>HTML5</strong>), then there is an additional function protocol that you can use when adding functions to scripts, which is to
prefix a function name with <tt>gmcallback_</tt>, for example:</p>
<p class="code">gmcallback_create_button</p>
<p>Using the above function name would mean that the function <tt>gmcallback_create_button()</tt> will not be obfuscated and so can be used in JavaScript extensions and other areas of your game, for example, when using the <a href="../GML_Reference/Web_And_HTML5/Web_And_HTML5.htm"><tt>clickable_*</tt></a> functions.</p>
<p> </p>
<p> </p>
<p> </p>
<div class="footer">
<div class="buttons">
<div class="clear">
<div style="float:left">Back: <a href="GML_Overview.htm">GML Overview</a></div>
<div style="float:right">Next: <a href="Method_Variables.htm">Method Variables</a></div>
</div>
</div>
<h5>© Copyright YoYo Games Ltd. 2020 All Rights Reserved</h5>
</div>
<!-- KEYWORDS
Script Functions
User Defined Functions
function
gmcallback
-->
<!-- TAGS
script_functions
-->
</body></html>