Skip to content
Engine

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:

  1. Save player data with DataService.
  2. Add a currency with EconomySystem.
  3. Define a validated remote with NetworkService.
  4. 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.

Server Script
local Engine = require(game:GetService("ServerScriptService"):WaitForChild("Engine"))
LocalScript
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.

Server Script: Data
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.

Server Script: Economy
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.

ModuleScript: ReplicatedStorage.Remotes
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 },
	}),
}
Server Script: Coins
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.

LocalScript
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:

ModuleScript: Engine/Configuration/EconomySystem
return {
	TradeTimeoutSeconds = 60,
}

See Configuration for the details.

Next steps