Phases
In Roblox, you might be familiar with the RunService. You can think of events
like Heartbeat
, PreRender
, or PostSimulation
as Phases.
All a Phase is, is a sync point within the execution of a frame. You can see the order of execution of a frame in Roblox in this image.
The 'Events' shown in this image represent the different sync points, or Phases that Roblox provides in a frame, all being ran in an explicit order.
In Planck, we represent Phases as an Object which you can assign to Systems. You can create, insert, and add a Phase to a system like so,
local Planck = require("@packages/Planck")
local Scheduler = Planck.Scheduler
local Phase = Planck.Phase
-- ...
local systemA = require("@shared/systems/systemA")
local myPhase = Phase.new("myPhase")
local scheduler = Scheduler.new(world, state)
:insert(myPhase)
:addSystem(systemA, myPhase)
Remember SystemTables? Instead of setting the phase in addSystem
, you can
add it to your SystemTable and the system will be added to that Phase.
We can also assign Phases to Events and Signals.
-- ...
local systemA = require("@shared/systems/systemA")
local myPhase = Phase.new("myPhase")
local scheduler = Scheduler.new(world, state)
:insert(myPhase, RunService, "Heartbeat")
:addSystem(systemA, myPhase)
Built-in Phases
Planck provides built-in Phases like Startup Phases and also provides a Plugin for Roblox RunService that adds Pipelines and Phases for each RunService Event.
While you're just getting started, it is suggested that you use these built-in phases for now. You will learn about deciding to make a Phase (and Pipelines) later.
Startup Phases
Startup Phases are a special kind of Phase. Planck will only run these systems once, and before any other system is ran.
- PreStartup
- Startup
- PostStartup
local Planck = require("@packages/Planck")
local Phase = Planck.Phase
local PreStartup = Phase.PreStartup
local Startup = Phase.Startup
local PostStartup = Phase.PostStartup
These Phases are useful for initialization work that you need to do once, and before you start your game loop.
RunService Phases Plugin
Planck provides a plugin that adds built-in Phases and Pipelines for each RunService event.
Installation
With Wally,
[dependencies]
PlanckRunService = "yetanotherclown/planck-runservice@0.2.0-rc.1"
Pipelines
Each RunService Event is now it's own Pipeline,
- PreRender
- PreAnimation
- PreSimulation
- PostSimulation
- Heartbeat
You might be more familiar with the old names for some of these events.
PreRender
is equivalent toRenderStepped
PreSimulation
is equivalent toStepped
local PlanckRunService = require("@packages/PlanckRunService")
local Pipelines = PlanckRunService.Pipelines
local PreRender = Pipelines.PreRender
local PreAnimation = Pipelines.PreAnimation
local PreSimulation = Pipelines.PreSimulation
local PostSimulation = Pipelines.PostSimulation
local Heartbeat = Pipelines.Heartbeat
Phases
And it's own Phase, with the exception of Heartbeat
which has many Phases.
Event | Phase |
---|---|
PreRender | PreRender |
PreAnimation | PreAnimation |
PreSimulation | PreSimulation |
PostSimulation | PostSimulation |
Heartbeat | Update |
local PlanckRunService = require("@packages/PlanckRunService")
local Phases = PlanckRunService.Phases
local PreRender = Phases.PreRender
local PreAnimation = Phases.PreAnimation
local PreSimulation = Phases.PreSimulation
local PostSimulation = Phases.PostSimulation
local Update = Phases.Update
More Update Phases
RunService.Heartbeat
isn't just a single Phase, instead its composed of
many Phases. This is because the Update Phases are where most of your
game's logic will run on, so we believe it's important that you can
express the order of execution easily right out of the box.
- First
- PreUpdate
- Update
- PostUpdate
- Last
local PlanckRunService = require("@packages/PlanckRunService")
local Phases = PlanckRunService.Phases
local First = Phases.First
local PreUpdate = Phases.PreUpdate
local Update = Phases.Update
local PostUpdate = Phases.PostUpdate
local Last = Phases.Last
What's Next?
Now that we know about Phases, it's time to learn how to explicitly define our order of execution.