update rules

This commit is contained in:
Joe 2026-02-02 14:05:11 -06:00
parent 4c390fdd37
commit d5522b2fef
8549 changed files with 11783 additions and 1888 deletions

View file

@ -0,0 +1,270 @@
---
title: Server authority model
description: The server authority model lets you build responsive cheat-free competitive experiences such as FPS, racing, sports, and combat.
---
import BetaAlert from '../../includes/beta-features/beta-alert.md'
<BetaAlert betaName="Server Authority Core API" leadIn="The server authority model and its associated APIs are currently in beta. Enable them in Studio through " leadOut="." components={props.components} />
<Alert severity="error">
As this feature is currently in beta, you should **not** publish a server‑authoritative experience. Your players' clients will not yet have support for server authority APIs, so the published experience will not work correctly.
</Alert>
In a **server authority model**, the server is the single **source of truth** for the entire experience state, and clients are only trusted to report their own inputs. This architecture is the core netcode foundation of a fair, competitive experience because it prevents entire classes of cheating like flyhacks or speedhacks by never trusting a client to report its own position or state.
## Advantages
In a naive server-owned system, clients would simply send their inputs to the server and display the results of the experience sent back by the server. While technically correct, such a system would face significant **input latency** because every player action would have to travel to the server, be processed, and have the result sent back to the client before it could be displayed. For most experiences, especially those fast‑paced, that round‑trip delay would cause gameplay to feel laggy, unresponsive, and unplayable.
In Roblox's **server authority** model, latency is compensated for by having clients instantly [predict](#client-prediction) the effects of their inputs in addition to sending them to the server. For example, when a player presses a key, the client doesn't wait for the server to respond; instead it **predicts** a few frames ahead of the last known server state. This allows the client to show the result of the input action instantly, effectively hiding network latency and making the experience feel responsive.
Sometimes the client will get its prediction wrong ([misprediction](#client-misprediction)) and, because of network latency, the client will not know that it has made a mistake for a few frames. For example:
<Alert severity="warning" variant="outlined">
Your client predicts that you've moved forward, but on the server another player used a stun ability that stopped you from moving. The client and server now have different states.
</Alert>
When a misprediction is detected, the client must correct its prediction based on the server's **authoritative state**. If the authoritative state is different from the client's predicted state, the client must [roll back and resimulate](#rollback-and-resimulation) its predicted frames. This system of client‑side prediction, rollback, and resimulation is known as "latency&nbsp;compensation" and helps make server‑authoritative multiplayer experiences feel smooth and responsive.
<Alert severity="info">
Mispredictions are a **normal and expected** part of the server authority architecture because clients inherently cannot predict other players' inputs, so actions by other players will always trigger some amount of misprediction. When tuned correctly, the resulting corrections are small and should be imperceptible to players. Read further on [advanced techniques](./techniques.md) to smooth out and mask network artifacts.
</Alert>
## Setup
As the server authority model requires certain other engine technologies to function correctly, you must first set the following properties on the `Class.Workspace` object in the [Explorer](../../studio/explorer.md):
1. `Class.Workspace.NextGenerationReplication` must be enabled
2. `Class.Workspace.PlayerScriptsUseInputActionSystem` must be enabled
3. `Class.Workspace.SignalBehavior` must be `Enum.SignalBehavior.Deferred|Deferred`
4. `Class.Workspace.UseFixedSimulation` must be enabled
5. `Class.Workspace.StreamingEnabled` must be enabled
6. `Class.Workspace.AuthorityMode` must be `Enum.AuthorityMode.Server|Server` (all of the above must be set first)
## Concepts
The server authority system runs on a few core concepts as follows.
### Client prediction
Through **client prediction**, the client simulates a few frames ahead of the last known server state to predict the effects of player inputs immediately. This hides input latency, but the prediction may later turn out to be incorrect ([client misprediction](#client-misprediction)) and thus require correction. The client tries to simulate just far enough ahead of the last known authoritative server state so that its inputs arrive on the server at the intended frame. The number of frames the client will predict ahead of the known server state is based on the latency behind the client and server.
### Client misprediction
When the client receives the authoritative state from the server, it checks that state against a historical record of what it predicted locally for that frame. When there is a difference between what the client [predicted](#client-prediction) and what the server actually did, this is a **misprediction**. Mispredictions can occur for several reasons, including shifts in network latency, other players acting in ways the client didn't anticipate, the experience running certain logic exclusively on the server, etc.
If the authoritative state is different from the client's predicted state, the client must [roll back and resimulate](#rollback-and-resimulation).
### Rollback and resimulation
When a client detects a [misprediction](#client-misprediction), it must reset to the server's authoritative state and then resimulate to jump back to its predicted frame. Based on the network latency, the client tries to simulate just far enough ahead of the last known authoritative server state so that its inputs arrive on the server at the intended frame.
```mermaid
block-beta
columns 1
block:Client
columns 7
ClientHeader("<span style="color:white;"><b>Client</b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>")
space:6
C1["3"]
C2["4"]
C3["5"]
C4["6"]
C5["<span style="font-size:80%">3 4 5 6</span> 7"]
C6["8"]
C7["9"]
end
block:Middle
columns 10
TimeStart("<span style="color:Grey; font-size:80%;">TIME</span>")
space:8
TimeEnd(" ")
space:10
end
block:Server
columns 7
ServerHeader(["<span style="color:white;"><b>Server</b> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>"])
space:6
S1["1"]
S2["2"]
S3["3"]
S4["4"]
S5["5"]
S6["6"]
S7["7"]
end
TimeStart --> TimeEnd
C1 --"<span style="color:white; background-color:RoyalBlue;">&nbsp; Input (Frame 3) &nbsp;</span>"--> S3
S3 --"<span style="color:white; background-color:SeaGreen;">&nbsp; Server State (Frame 3) &nbsp;</span>"--> C5
style Client fill:RoyalBlue
style ClientHeader stroke-opacity:0, fill-opacity:0
style Middle fill-opacity:0, stroke-opacity:0
style TimeStart fill-opacity:75%, stroke-opacity:75%
style TimeEnd display:none
style Server fill:SeaGreen
style ServerHeader stroke-opacity:0, fill-opacity:0
```
<figure>
<figcaption>In the above diagram, the client is simulating 2 frames ahead of the server. It sends its inputs for frame 3 which arrive at the intended frame (3) on the server. The server sends the authoritative state for frame 3 and the client receives it on frame 7. The client discovers it mispredicted frame 3 so it resets to the server's frame 3 and resimulates frames 4, 5 and 6 before it simulates frame 7. Players may see a noticeable network artifact such as a sudden movement.</figcaption>
</figure>
In summary, the **client**:
1. Receives the **authoritative state** from the server and compares it against its own **predicted state**.
2. If the client's prediction was incorrect:
1. Client rolls back to the last known authoritative state received from the server.
2. Client resimulates from the authoritative state to its predicted state, re-applying any local inputs.
## Implementation
### Network ownership and prediction
In the server authority model, you're able to keep the core gameplay objects server‑owned without incurring the input latency cost normally associated with server ownership. Things like cars, player characters, or other gameplay‑critical objects can remain server‑owned, even when interacting with other players.
By default, Roblox will automatically predict the physics properties of `Class.BasePart|BaseParts` near the local player `Class.Player.Character|Character`, but if you want more fine‑grained control, you can explicitly force an instance's prediction on or off with `Class.RunService:SetPredictionMode()`.
<Alert severity="success">
Roblox synchronizes all relevant physics properties automatically.
</Alert>
### Simulation sync
In the server authority model, the client and the server must both run the core simulation, and the client's simulation needs to be able to [roll back and resimulate](#rollback-and-resimulation) when a [misprediction](#client-misprediction) occurs. To enable this, write your core logic inside functions bound through `Class.RunService:BindToSimulation()` in a `Class.ModuleScript` that's initialized on both the client and server.
<img src="../../assets/studio/explorer/ReplicatedStorage-Server-Authority.png" width="320" alt="Server authority setup" />
```lua title="Simulation (ModuleScript)"
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local Simulation = {}
Simulation.Initialize = function()
RunService:BindToSimulation(function(deltaTime)
-- Read player inputs
-- Update experience state
end)
end
return Simulation
```
```lua title="ServerLoader (Server Script)"
local Simulation = require(script.Parent)
Simulation:Initialize()
```
```lua title="ClientLoader (Client Script)"
local Simulation = require(script.Parent)
Simulation:Initialize()
```
During a resimulation, Roblox will re-run the functions bound to the simulation via `Class.RunService:BindToSimulation()|BindToSimulation()`. Processing player inputs, interacting with synchronized physics objects, and updating the core experience state should live inside those bound functions.
### State sync with attributes
Roblox automatically synchronizes all relevant physics properties on predicted instances. For custom data, [attributes](../../studio/properties.md#instance-attributes) are the primary way to synchronize instances marked as predicted; on such instances, any mismatch in attribute values between the server's source of truth and the client's prediction will trigger a full [rollback and resimulation](#rollback-and-resimulation).
<Alert severity="success">
Use attributes to store experience data that affects your core simulation, including player health, ammunition, inventory, or custom rules (see [limitations](#attribute-limits)).
</Alert>
<Alert severity="warning">
Only write to attributes on **predicted** instances from within functions bound through `Class.RunService:BindToSimulation()|BindToSimulation()` to ensure that Roblox can fully track relevant experience states and resimulate properly.
</Alert>
#### Attribute limits
In order to be replicated, an attribute must meet all of the following criteria:
- It is among the first 64 attributes on its `Class.Instance`.
- Its name contains at most 50 characters.
- If a string type attribute, its value contains at most 50 characters.
#### Physical properties
The server authority system predicts physical properties such as the ones below. Note that this is **not** an exhaustive list but rather an illustration of classes and property types that will be considered.
- `Class.BasePart` — `Class.BasePart.CFrame|CFrame`; `Class.BasePart.RotVelocity|RotVelocity`; `Class.BasePart.Velocity|Velocity` (if assembly root); `Class.BasePart.CurrentPhysicalProperties|CurrentPhysicalProperties`; `Class.BasePart.CanCollide|CanCollide`; `Class.BasePart.Mass|Mass`; `Class.BasePart.Size|Size`
- `Class.WeldConstraint` — `Class.WeldConstraint.Enabled|Enabled`; `Class.WeldConstraint.CFrame1|CFrame1`; `Class.WeldConstraint.CFrame2|CFrame2`
- `Class.Constraint` — `Class.Constraint.Enabled|Enabled`; any non-redundant readable/writable property
- `Class.Attachment` — `Class.Attachment.CFrame|CFrame`
- `Class.Motor` — `Class.Motor.CurrentAngle|CurrentAngle`; `Class.Motor.DesiredAngle|DesiredAngle`; `Class.Motor.MaxVelocity|MaxVelocity`
- `Class.Humanoid` — `Class.Humanoid.Jump|Jump`; `Class.Humanoid.MoveDirection|MoveDirection`; `Class.Humanoid.AutoRotate|AutoRotate`
- `Class.ControllerManager`
### Input actions
In a server-authoritative experience, the primary way for a client to affect the experience's state is through the [Input Action System](../../input/input-action-system.md). These inputs are sent to the server and are replayed during resimulation on the client. As a result, `Class.InputAction|InputActions` should be used for **all inputs that affect the core simulation** and they should be checked for sanity before they're processed.
<Alert severity="warning">
To reiterate, do not use traditional events like `Class.UserInputService.InputBegan` in the core simulation of a server-authoritative experience.
</Alert>
Note that `Class.InputContext|InputContexts` must be a descendent of a `Class.Player` so that the engine knows who has ownership over the `Class.InputContext`. Placement in `Class.StarterGui` is fine, since it replicates to the player's `Class.PlayerGui` at join time and effectively descends from that `Class.Player`.
<img src="../../assets/studio/explorer/StarterGui-InputContext-InputAction-InputBinding-All.png" width="320" />
Using this pattern, you can read `Class.InputAction|InputActions` for all players in `Class.RunService:BindToSimulation()` on both client and server to receive the same data for a given frame and record the previous frame's input in an [attribute](../../studio/properties.md#instance-attributes), for example to trigger a character sprint when a `CharacterSprint` input action is triggered.
Note that if you need to write custom data into the [Input Action System](../../input/input-action-system.md), you should use a function connected to `Class.RunService.RenderStepped` or `Class.RunService:BindToRenderStep()`, not `Class.RunService:BindToSimulation()`. Firing an `Class.InputAction` in `Class.RunService:BindToSimulation()|BindToSimulation()` can cause clients to produce incorrect results during a resimulation.
```lua
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local Workspace = game:GetService("Workspace")
RunService:BindToRenderStep("CameraInput", Enum.RenderPriority.Last.Value, function()
-- Send the client camera's forward vector to the server through an InputAction
local cameraForwardInputAction = Players.LocalPlayer.PlayContext.CameraForward
local cameraForwardVector = Workspace.CurrentCamera.CFrame.LookVector
cameraForwardInputAction:Fire(cameraForwardVector)
end)
```
### Remote events
[Remote events](../../scripting/events/remote.md) can still be used within the server authority model to facilitate discrete communication between client and server. For example, servers can use remote events to broadcast data about players scoring points or picking up objects, and clients can use remote events as an alternative API for sending inputs to the server, such as for button presses or tapping objects in the 3D world.
### Animations, sounds, and effects
Client-side effects like animations and sounds must be written knowing that the client simulation is merely a prediction of the authoritative server state. `Class.RunService:BindToSimulation()|BindToSimulation()` limits what properties and methods can be called from within bound functions to help guide you in writing only to the synchronized simulation state. Displaying the results of this simulation, triggering effects and sounds, etc. should be done in a separate function connected to `Class.RunService.RenderStepped|RenderStepped` that reads the results of the simulation and triggers the desired effects.
Further guidance around rendering a predicted simulation is covered in the [advanced techniques](./techniques.md) guide.
## Example projects
In addition to this documentation, the following templates can help you get started:
<GridContainer numColumns="3">
<figure>
<a href="https://www.roblox.com/games/134686834388911/Racing-Server-Authority-Template"><img src="../../assets/misc/SA-Icon-Racing.jpg" /></a>
<figcaption>Racing</figcaption>
</figure>
<figure>
<a href="https://www.roblox.com/games/110687099504272/Soccer-Server-Authority-Template"><img src="../../assets/misc/SA-Icon-Soccer.jpg" /></a>
<figcaption>Soccer</figcaption>
</figure>
<figure>
<a href="https://www.roblox.com/games/90572444221193/Laser-Tag-Server-Authority-Template"><img src="../../assets/misc/SA-Icon-Laser-Tag.jpg" /></a>
<figcaption>Laser Tag</figcaption>
</figure>
</GridContainer>

View file

@ -0,0 +1,268 @@
---
title: Server authority advanced techniques
description: Advanced techniques for creating high-quality, smooth, multiplayer experiences using the server authority model.
---
import BetaAlert from '../../includes/beta-features/beta-alert.md'
This guide covers advanced techniques for creating high-quality, smooth, multiplayer experiences using the [server authority model](./index.md).
<BetaAlert betaName="Server Authority Core API" leadIn="The server authority model and its associated APIs are currently in beta. Enable them in Studio through " leadOut="." components={props.components} />
<Alert severity="error">
As this feature is currently in beta, you should **not** publish a server‑authoritative experience. Your players' clients will not yet have support for server authority APIs, so the published experience will not work correctly.
</Alert>
## Position smoothing
You can visually smooth out the position of mispredicted synchronized objects by rendering a different object than what is being simulated.
1. Make the **simulated** object invisible.
2. Make a **renderer** object as a massless, non‑collidable, visual‑only clone to track the simulated object.
3. Attach a script to the renderer object that smoothly tracks the position of the invisible, simulated object. This separation between rendering and simulation lets you alter the position of the renderer object to create a visually smooth experience.
In the following sample `Class.Script`, the rendered object (parent) smoothly tracks the simulated object. The rendered object is always slightly "behind" the simulated object which is typically fine but may be undesirable in certain situations.
```lua title="Smoothly Track BasePart Position with Renderer Part"
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local Workspace = game:GetService("Workspace")
-- Object to smoothly track
local smoothTarget:BasePart = Workspace.SimulatedPart
-- Visual object that will be smoothed
local renderer:BasePart = script.Parent
-- Time to smooth over; smaller means faster
local smoothTime = 0.07
-- Store data needed to compute the smooth position
local smoothVelocity = Vector3.new()
-- Disable the renderer object's physics
renderer.Massless = true
renderer.Anchored = true
renderer.CanCollide = false
RunService.RenderStepped:Connect(function(deltaTime: number)
-- Smoothly track the target object
local smoothPosition, smoothVelocity = TweenService:SmoothDamp(
renderer.Position,
smoothTarget.Position,
smoothVelocity,
smoothTime,
math.huge,
deltaTime)
renderer.Position = smoothPosition
end)
```
The [Soccer](https://www.roblox.com/games/110687099504272/Soccer-Server-Authority-Template) example experience uses a variation of this technique to more intelligently turn on and off position smoothing for the soccer ball. Specifically, the soccer ball only smooths its position when the simulated ball has "jumped" far enough away from the rendered ball. This approach provides the best of both worlds: the soccer ball has no visual latency under normal conditions, and the experience smoothly interpolates its position only after the simulated ball has unexpectedly jumped to a new location, likely due to a network artifact or server‑side change.
## Animations, sounds, and visual effects
In a predicted simulation, it's possible to trigger effects, sounds, or animations for events that the client predicted would happen but which never occurred on the server. The rendering system should be prepared to "undo" any mispredicted effects. For example, a client might predict that a grenade exploded and trigger a particle effect, but if another player diffused the grenade, the client should hide the particle effect.
A good strategy for rendering a predicted simulation is to synchronize a state machine pattern within the simulation loop and render changes to the state in a render step function. The following example simulates a grenade with a state machine pattern:
```lua title="Simple State Machine for Tracking a Grenade (ModuleScript)"
local Workspace = game:GetService("Workspace")
local module = {}
module.GrenadeStates = {
Idle = 0,
Lit = 1,
Exploded = 2,
Defused = 3,
}
module.GrenadeExplodeTime = 3.0
module.Initialize = function(grenade)
RunService:BindToSimulation(function(deltaTime)
-- Initialize empty grenade state
local grenadeState = grenade:GetAttribute("State")
if grenadeState == nil then
grenadeState = module.GrenadeStates.Idle
grenade:SetAttribute("State", grenadeState)
grenade:SetAttribute("Timer", 0.0)
end
-- Increment grenade timer
local timer = grenade:GetAttribute("Timer")
timer = timer + deltaTime
grenade:SetAttribute("Timer", timer)
-- Explode lit grenades
if grenadeState == module.GrenadeStates.Lit then
if timer >= module.GrenadeExplodeTime then
grenadeState = module.GrenadeStates.Exploded
grenade:SetAttribute("State", grenadeState)
grenade:SetAttribute("Timer", 0.0)
end
end
end)
end
return module
```
With the previous state machine in place, you can render grenade effects in a `Class.RunService.RenderStepped` connection within a separate script based on the synchronized grenade state:
```lua title="Render Particles and Sounds based on the Synchronized Grenade State"
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RunService = game:GetService("RunService")
local Simulation = require(ReplicatedStorage.Simulation)
local grenade = script.Parent
local previousGrenadeState = nil
-- Highlight instance to indicate grenade state
local highlight = Instance.new("Highlight")
highlight.Parent = grenade
highlight.FillTransparency = 1
highlight.OutlineTransparency = 1
highlight.DepthMode = Enum.HighlightDepthMode.Occluded
RunService.RenderStepped:Connect(function(deltaTime: number)
local grenadeState = grenade:GetAttribute("State")
local grenadeTimer = grenade:GetAttribute("Timer")
-- Emit the lit particles if the grenade is lit
grenade.LitEmitter.Enabled = grenadeState == Simulation.GrenadeStates.Lit
-- Play the explosion emitter if the grenade just exploded
if previousGrenadeState ~= grenadeState then
if grenadeState == Simulation.GrenadeStates.Exploded and grenadeTimer < 0.2 then
grenade.ExplosionEmitter:Emit(100)
grenade.ExplosionSound:Play()
end
previousGrenadeState = grenadeState
end
-- Change the grenade's highlight color based on the state and time
if grenadeState == Simulation.GrenadeStates.Lit then
highlight.FillColor = Color3.fromRGB(255, 0, 0)
highlight.FillTransparency = 1 - (grenadeTimer / Simulation.GrenadeExplodeTime)
elseif grenadeState == Simulation.GrenadeStates.Idle then
highlight.FillTransparency = 1
elseif grenadeState == Simulation.GrenadeStates.Exploded then
highlight.FillTransparency = 1
elseif grenadeState == Simulation.GrenadeStates.Defused then
highlight.FillColor = Color3.fromRGB(0, 255, 125)
highlight.FillTransparency = 0.5
end
end)
```
## Designing around network latency
Certain gameplay mechanics lend themselves better to networked multiplayer than other mechanics. Players will always have some delay between when another player performs an action and when they receive that player's input. The best way to create a super smooth multiplayer experience is to design your experience with these limitations in mind.
For example, an experience with slower acceleration on player movement will appear smoother than one with higher acceleration because the difference in position caused by the network latency of player input will be less than in an experience with higher acceleration.
As another example, a gameplay mechanic where players can **instantly** trigger a large explosion by pressing an input will have more network artifacts than if the explosion is delayed after the input, as if by lighting a fuse. This puts the resimulation on the fuse effect instead of on the explosion effect which is a less noticeable network artifact.
## Predicting other player inputs
By default, Roblox does not forward the inputs from each client to every other client. Whether this is right for your experience depends on its design:
- For basic humanoid movement, the default behavior means that other player characters' movements are not extrapolated from the authoritative server state and, as a result, other player characters will not mispredict but will render slightly in the past.
- In a racing game, by contrast, the default behavior means that clients will not know whether other players are applying the throttle or other inputs, so other cars may appear behind the local player even if they're actually ahead. To alleviate this, you can store player inputs in [attributes](../../studio/properties.md#instance-attributes) on the server and operate on those synchronized attributes client‑side using `Class.RunService:BindToSimulation()` as demonstrated in the following code sample and the [Racing](https://www.roblox.com/games/134686834388911/Racing-Server-Authority-Template) template. This approach lets you use attributes as inputs to your simulation to have fully replicated player inputs.
```lua title="Storing Player Input in Attributes (ModuleScript)"
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local module = {}
module.storePlayerInput = function(player:Player, humanoidRootPart:BasePart)
local inputContext:InputContext = player.PlayerGui.InputContext
local throttle = inputContext.DefuseAction:GetState()
humanoidRootPart:SetAttribute("Throttle", throttle)
-- Write any other inputs into attributes...
end
module.Initialize = function()
RunService:BindToSimulation(function(deltaTime)
if RunService:IsServer() then
-- Forward inputs from server to all clients
for _, player in Players:GetPlayers() do
local humanoidRootPart:BasePart = player.Character.HumanoidRootPart
local inputContext:InputContext = player.PlayerGui.InputContext
module.storePlayerInput(player, humanoidRootPart)
end
else
-- Write local player inputs as attributes
local player = Players.LocalPlayer
local humanoidRootPart:BasePart = player.Character.HumanoidRootPart
local inputContext:InputContext = player.PlayerGui.InputContext
module.storePlayerInput(player, humanoidRootPart)
end
-- Use the attributes as inputs to the game
for _, player in Players:GetPlayers() do
local humanoidRootPart:BasePart = player.Character.HumanoidRootPart
local throttle = humanoidRootPart:GetAttribute("Throttle")
if throttle then
-- Apply the throttle to the player's vehicle
end
end
end)
end)
return module
```
## Debugging
There are some new tools and techniques you can use to debug a server‑authoritative experience.
### Server authority visualizer
Pressing <kbd>Ctrl</kbd><kbd>Shift</kbd><kbd>F6</kbd> (Windows) or <kbd>⌘</kbd><kbd>Shift</kbd><kbd>F6</kbd> (Mac) opens Studio's **server authority visualizer** which shows several key pieces of information:
<table size="small">
<thead>
<tr>
<th width="35%">Details</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>**Instance prediction success rate**</td>
<td>The percentage of correctly predicted instances over the last 8 seconds.</td>
</tr>
<tr>
<td>**Input accept rate**</td>
<td>The percentage of all players' inputs that arrived on time on the server. Late inputs will lower this number.</td>
</tr>
<tr>
<td>**Client-server step delta**</td>
<td>The number of frames between the client and the server, including the join time of the client. The stability of this number represents the stability of your connection to the server.</td>
</tr>
<tr>
<td>**RCC heartbeat FPS**</td>
<td>The frame rate of the simulation on the server. If this number drops below 59, the server cannot keep up with the simulation and the experience will degrade in quality.</td>
</tr>
<tr>
<td>**Predicted instance count**</td>
<td>The number of instances your client is [predicting](./index.md#client-prediction).</td>
</tr>
<tr>
<td>**Input drop reason counts**</td>
<td>
The number of times the server has dropped an input for each reason:
- **[x] too old** — The inputs arrived late, meaning your network worsened or the client could not keep up with the simulation.
- **[x] out of order** — A networking bug occurred that caused your inputs to be rearranged and discarded.
- **[x] buffer full** — The server could not buffer your input. Either your network suddenly improved or the server could not keep up with the simulation.
</td>
</tr>
</tbody>
</table>
### Simulation radius
When relying on automatic prediction (`Enum.PredictionMode.Automatic`), you can visualize the prediction radius around your player character by enabling **Are&nbsp;Regions&nbsp;Enabled** in Studio's settings (<kbd>Alt</kbd><kbd>S</kbd> on Windows; <kbd>⌥</kbd><kbd>S</kbd> on Mac). The green cylinder indicates the range around your character in which instances are predicted, and its radius grows and shrinks based on the performance characteristics of the device.
<img src="../../assets/studio/debugging/Server-Authority-Simulation-Radius.jpg" width="800" alt="Simulation radius around player character with server authority running" />