Getting Started
Quick Start
Build a small working game loop with Engine in a few minutes. Save player data, give players coins, show them on the client and send a remote safely.
This guide assumes Engine is installed. You will:
- Save player data with DataService.
- Add a currency with EconomySystem.
- Define a validated remote with NetworkService.
- Show live values on the client.
1. Require Engine
On the server, require the Engine module in ServerScriptService. On the client, require the copy Engine puts in ReplicatedStorage.
local Engine = require(game:GetService("ServerScriptService"):WaitForChild("Engine"))local Engine = require(game:GetService("ReplicatedStorage"):WaitForChild("Engine"))Then get what you need by name. The first call for a name loads that module, and every call after returns the same table.
local DataService = Engine:GetService("DataService")
local EconomySystem = Engine:GetSystem("EconomySystem")
local Promise = Engine:GetPackage("Promise")2. Save player data
Create a profile store with a template, and start a session when a player joins. The session saves automatically and ends by itself when the player leaves.
local Players = game:GetService("Players")
local Engine = require(game:GetService("ServerScriptService"):WaitForChild("Engine"))
local DataService = Engine:GetService("DataService")
local PlayerData = DataService:CreateProfileStore("PlayerData", {
Level = 1,
Wins = 0,
})
Players.PlayerAdded:Connect(function(player)
PlayerData:StartSessionAsync(PlayerData:PlayerKey(player), { Player = player, Create = true })
:andThen(function(profile)
profile:Reconcile()
end)
:catch(function(err)
warn(err)
player:Kick("Your data could not be loaded. Please rejoin.")
end)
end)Tip
In Studio, turn on Game Settings > Security > Enable Studio Access to API Services to test real saving. Without it, DataService uses a temporary in-memory store.
3. Add a currency
EconomySystem keeps balances in its own profile store and shows them in the player list with Leaderstat.
local Engine = require(game:GetService("ServerScriptService"):WaitForChild("Engine"))
local EconomySystem = Engine:GetSystem("EconomySystem")
EconomySystem:CreateCurrency("Coins", { Symbol = "C", Leaderstat = true })
EconomySystem:CreateReward("Daily", {
Currency = "Coins",
Amount = 100,
Cooldown = 24 * 3600,
})4. Define a remote
Put remote definitions in one ModuleScript in ReplicatedStorage so both sides use the same names and rules. The schema rejects bad arguments and the rate limit stops spam before your code runs.
local RunService = game:GetService("RunService")
local Engine = if RunService:IsServer()
then require(game:GetService("ServerScriptService"):WaitForChild("Engine"))
else require(game:GetService("ReplicatedStorage"):WaitForChild("Engine"))
local NetworkService = Engine:GetService("NetworkService")
local Guard = Engine:GetPackage("Guard")
return {
CollectCoin = NetworkService:DefineRemote("CollectCoin", {
Direction = "ClientToServer",
Schema = Guard.tuple(Guard.string({ MaxLength = 36 })),
RateLimit = { RatePerSec = 5, Burst = 10 },
}),
}local Engine = require(game:GetService("ServerScriptService"):WaitForChild("Engine"))
local EconomySystem = Engine:GetSystem("EconomySystem")
local Remotes = require(game:GetService("ReplicatedStorage"):WaitForChild("Remotes"))
Remotes.CollectCoin.Received:Connect(function(player, args)
local coinId = args[1]
if isNearCoin(player, coinId) then -- always check on the server
EconomySystem:Deposit(player, "Coins", 10, { Sku = "Coin" })
end
end)5. Show it on the client
The client half of EconomySystem keeps the local player's balances up to date.
local Engine = require(game:GetService("ReplicatedStorage"):WaitForChild("Engine"))
local EconomySystem = Engine:GetSystem("EconomySystem")
local Remotes = require(game:GetService("ReplicatedStorage"):WaitForChild("Remotes"))
local label = script.Parent
EconomySystem:GetBalanceAsync("Coins"):andThen(function(balance)
label.Text = EconomySystem:FormatBalance("Coins", balance)
end)
EconomySystem:OnBalanceChanged("Coins", function(balance)
label.Text = EconomySystem:FormatBalance("Coins", balance)
end)
-- When the player touches a coin
Remotes.CollectCoin:Fire(coinId)6. Change a setting
Every module has settings with defaults. To change one, add a ModuleScript named after the module to ServerScriptService.Engine.Configuration and return only what you change:
return {
TradeTimeoutSeconds = 60,
}See Configuration for the details.
Next steps
- Read Server and Client to understand what runs where.
- Learn the patterns every Engine API follows in API Conventions.
- Browse the services, systems and packages.