Replication
Replication is how HELIX keeps everyone in sync. When the server changes something -- moves an actor, updates a health value, spawns a new object -- replication is the system that pushes those changes out to all connected clients.
Actor Replication
Before an actor can be seen or interacted with by clients, it needs to be set up for replication. This tells the engine "hey, this thing exists on the network, keep clients informed about it."
- Blueprint
- Lua
- JavaScript
-- Enable replication on an actor
my_actor:SetReplicates(true)
my_actor:SetReplicateMovement(true)
// Enable replication on an actor
myActor.SetReplicates(true);
myActor.SetReplicateMovement(true);
SetReplicates(true) makes the actor network-visible. SetReplicateMovement(true) automatically syncs position, rotation, and velocity -- so you don't need to send those manually.
Replicated Variables
Sometimes you need to sync specific data, like a player's health or a door's open/closed state. That's where replicated variables come in.
- Blueprint
- Lua
- JavaScript
In Blueprints, you set a variable to Replicated or RepNotify in the variable's Details panel (right side). When you choose RepNotify, the engine auto-generates an OnRep_ function you can implement to react to changes on clients.
-- Store a custom value on the server (available on HPlayer)
my_player:SetValue("Health", 100.0)
-- Retrieve the value
local health = my_player:GetValue("Health")
print("Health: " .. tostring(health))
// JavaScript uses the endpoint/call model for server data.
// Use Helix.endpoint() to expose state and Helix.call() to retrieve it.
Helix.server(async () => {
Helix.endpoint('getHealth', async (helixId) => {
return { health: playerHealth[helixId] };
});
});
The ReplicatedUsing / callback pattern is especially useful -- it lets you react to changes on the client side, like updating a health bar when the value arrives.
Relevancy
Not every client needs to know about every actor. A player on the east side of your map doesn't need updates about a crate on the west side. Relevancy controls which actors replicate to which clients based on factors like:
- Distance -- Actors too far away stop replicating.
- Net Cull Distance -- You can set a custom cutoff distance per actor.
- Always Relevant -- Force an actor to replicate to everyone (use sparingly -- it's expensive on bandwidth).
Setting a net cull distance is straightforward:
- Blueprint
- Lua
- JavaScript
-- Set the maximum relevancy distance
my_actor.NetCullDistanceSquared = 225000000.0
// Set the maximum relevancy distance
myActor.NetCullDistanceSquared = 225000000.0;
Network Conditions
Keep in mind that real networks have latency, packet loss, and bandwidth limits. A few tips:
- Don't replicate every frame. Only sync values when they actually change.
- Use quantization. Rotations and positions can be compressed to save bandwidth.
- Batch updates. Group related changes together instead of sending them one at a time.
- Prioritize. Actors closer to the player should get updates more frequently than distant ones.
For more on how to send targeted messages between client and server, head over to Remote Calls.