This lesson will show you how you can create a state machine. A state machine is a way to code behaviours that have different states:
A door has two states: OPENED and CLOSED.
An enemy can have multiple states, for example: WANDER, FOLLOW_PLAYER, ATTACK, DEAD.
A UI with smooth animation: HIDDEN, FADE_IN, VISIBLE, FADE_OUT.
To spawn our objects, we will make a state machine with 3 states:
SPAWN_OBJECT: This state is just spawning the object in the scene and switching to the WAITING_DESTROY state
WAITING_DESTROY: This state is constantly looking if the coin is still there. If the coin is collected, then this state is moving to the COOLDOWN state
COOLDOWN: Wait a few seconds before going back to the SPAWN_OBJECT state.
Using a state machine is a great way to make various elements in your game using a code that is similar, making it easier to debug and for other people to understand.
Spawning an object from a script
Before making the state machine, we need a function that can spawn an object in the scene.
Create a group “Object Spawner” and add a new script called “ObjectSpawner” as a child.
Select the “ObjectSpawner” script and drag & drop the Coin template from your Project Content to the Custom Properties.
Now that we have the Asset Reference of the object, meaning the ID of the template, we can spawn it in our code using SpawnAsset:
When starting the Preview, a Coin is spawned inside the Object Spawner group.
Now that we know how to spawn the coin, we can create the State Machine. The full code is available below but let’s look at the different parts of this script:
First, we get the Custom Property Coin to retrieve the reference to the asset.
We declare a constant value COOLDOWN_DURATION that will be the number of seconds that the script will have to wait before spawning a new coin.
We declare useful variables for the script, spawnObject and nextSpawnAt.
We declare the various states of the State Machine and set the currentState.
We declare a function SpawnObject that uses the line we made just above.
We declare a function IsObjectInScene to detect when the object has been destroyed.
We declare a function SetState that will contain the logic when we are switching from one state to another one.
We declare a function CheckStates that will contain the logic to detect when we should move to another state.
We declare a function Tick that is called each frame by the engine.
We call the function SetState to spawn the first coin.
local COIN_TEMPLATE = script:GetCustomProperty("Coin")
-- This constant is the number of seconds before the next call to SpawnObjectlocal COOLDOWN_DURATION = 2-- spawnedObject: a reference to the spawned coin, it will be set when the object is spawnedlocal spawnedObject
-- nextSpawnAt: the value that stores the time of the next spawnlocal nextSpawnAt = 0-- The different states of the State Machinelocal STATE_SPAWNING = 1local STATE_WAITING_DESTROY = 2local STATE_COOLDOWN = 3-- currentState is the current state of the State Machinelocal currentState
-- The function to spawn an objectfunctionSpawnObject()
spawnedObj = World.SpawnAsset(COIN_TEMPLATE, { parent = script.parent })
end-- A function that returns true if the object exists.-- if obj is nil, meaning not defined, it will return false-- if obj is defined but obj:IsValid() returns false, it means that the coin has been destroyed-- IsObjectInScene returns false if the object is destroyedfunctionIsObjectInScene(obj)return obj and obj:IsValid()
end-- Updating statesfunctionSetState(newState)if newState == STATE_SPAWNING then
SpawnObject()
elseif newState == STATE_WAITING_DESTROY then--do nothingelseif newState == STATE_COOLDOWN then-- Saving the nextSpawnTime which is the number of seconds + the cooldown
nextSpawnAt = time() + COOLDOWN_DURATION
end
currentState = newState
endfunctionCheckStates()-- If the state is "spawning", then we should move to waiting destroyif currentState == STATE_SPAWNING then
SetState(STATE_WAITING_DESTROY)
-- If we are waiting for the object to be collected and-- if IsObjectInScene returns false ("not false" means true), the condition is valid-- We are starting the cooldownelseif currentState == STATE_WAITING_DESTROY andnot IsObjectInScene(spawnedObj) then
SetState(STATE_COOLDOWN)
-- If the time() is greater than nextSpawnAt, we should spawn the coinelseif currentState == STATE_COOLDOWN andtime() >= nextSpawnAt then
SetState(STATE_SPAWNING)
endend-- This function is called at each framefunctionTick()
CheckStates()
end
SetState(STATE_SPAWNING)Code language:Lua(lua)
Object Spawner as a template
Now that the object spawner is working, we can Create a New Template From This and put several instances of them on the map.
This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.
Strictly Necessary Cookies
Strictly Necessary Cookie should be enabled at all times so that we can save your preferences for cookie settings.
If you disable this cookie, we will not be able to save your preferences. This means that every time you visit this website you will need to enable or disable cookies again.
3rd Party Cookies
This website uses Google Analytics to collect anonymous information such as the number of visitors to the site, and the most popular pages.
Keeping this cookie enabled helps us to improve our website.
Please enable Strictly Necessary Cookies first so that we can save your preferences!