Scripting allows defining how your game (or interactive movie) will behave and react to player input. It allows taking actions in response to events like a button being pressed, time passing by and more.
In the long term, CraftStudio will sport a visual scripting system. For now though, scripts are written in Lua, a pretty simple programming language. You might want to check out this Lua crash course.
You might want to check out the Scripting Reference which details all the functions made available by CraftStudio to your scripts.
A script defines a behavior for one or more objects of your game.
Once created, a script can be attached to one or more game objects in a scene by adding a Scripted Behavior component. That means you can reuse the same scripts on multiple objects, for instance to share a behavior for a set of similar objects (think same type of enemies or a bunch of doors which must all react in the same way).
Anatomy of a scripted behaviorEdit
When created, a scripted behavior defines two recipes (or "functions" in programming speak) which will be executed (or "called") at different occasions:
function Behavior:Awake() end function Behavior:Update() end
- The function named Awake will be called when a game object featuring this script comes to live. Game objects can be created when a scene is loaded or on demand while the game is running.
- The function named Update will be called 60 times a second for each game object featuring this script.
Awake should be used to do your one-time setup (if any) and Update will contain your script's logic as time passes by.
(A third function called Behavior:Start can also be added to your script. If it exists, it will be executed after all Awake functions have been executed but before the first Update of any object happens. It might come in handy when you need to initialize stuff in a specific order)
Your first script: moving a game object over time!Edit
Ok so let's get started with something really simple: make an object move as time goes by.
We're going to add a single line between the start and end of the Update function:
function Behavior:Update() self.gameObject.transform:MoveLocal( Vector3:New( 0.01, 0, 0 ) ) end
self represents the current incarnation of our script. By using dots, we can access its properties. So self.gameObject is the game object our behavior component was attached to. This game object, in turn, owns a transform component, which manages the object's position, orientation and scale.
Finally, the transform component provides a function named MoveLocal. Calling this function will update our game object's position by offsetting it with the specified values on each axis: 0.01, 0 and 0 respectively X, Y and Z.
Note that when calling a function relating to a particular component or object, we have to use a colon, not a dot just before the function name. The colon indicates that the recipe / function on the right affects the object defined on the left.
Making decisions: only move when a key is pressedEdit
We can make our game interactive by adding conditions. if blocks only execute the enclosed code if the condition is true.
function Behavior:Update() if CraftStudio.Input.IsButtonDown( "Fire" ) then self.gameObject.transform:MoveLocal( Vector3:New( 0.01, 0, 0 ) ) end end
In this snippet, we call the global (that is, accessible from anywhere) CraftStudio.Input.IsButtonDown function, which tells us if a particular button is down (the condition is then true) or not (the condition would then be false and the code between then and end would be skipped)
Remember that our Behavior:Update function is called 60 times a second, so the object will only move when the button is down and will stay still as soon as we release it.
Tracking state (health, armor, whatever)Edit
Even though we might be reusing the same script on several game objects, it's possible to track state independently for each of those game objects. To attach some state (a health counter, a name or anything else) to a specific instance of your script, you should bind variables to the self object.
For instance, we could keep track of how many bullets a game object has:
function Behavior:Start() self.bullets = 100 end function Behavior:Update() if [some condition that would make the enemy fire] then self.bullets = self.bullets - 1 if self.bullets == 0 then print( "Out of bullets!" ) end end end
Multiple enemies could use this script and they would each keep track of their own bullets, instead of drawing from the same pool if we hadn't used self.
There are two ways to interact with your game:
- Through the scene, by calling functions on game objects or their components, like the MoveLocal function we just discovered.
- Through the global CraftStudio table which provides access to global features like game controls (CraftStudio.Input), or functions like loading another scene (CraftStudio.LoadScene).
For a complete list of those functions and how they work, check out the Scripting Reference.