How often should RemoteEvents be fired to the server, in terms of maintaining performance?

In my game, I’ve made a system that causes a player character’s head to turn as they turn their camera, this is done by modifying the C1 value of the character’s Neck joint Motor6D based on their current camera angle, done in a function bound to RenderStepped. I thought this would replicate since many actions done to a player character will replicate, but seeing as it doesn’t, I needed to implement a system that would allow this behavior to replicate to other clients, which would in turn require remotes as clients can’t directly access the CurrentCamera of other clients (to my knowledge, anyways).

The way I did this was have each client periodically send the CFrame of its CurrentCamera to the server through a RemoteEvent. The server then modifies a CFrameValue parented to the respective Player instance that tracks the CFrame reported by the client. Then, back on the client side, the RenderStepped function iterates through each Player, reads their CFrameValue, calculates what the C1 value of their character’s neck joint should be, and lerps it to that target angle for smooth turning.

Each client fires their RemoteEvent to the server roughly 20 times per second, and because I don’t quite have a full grasp on how much “stress” Luau can hold, so to speak, nor how taxing different types of calculations can be on performance, I was wondering if this rate was acceptable, too much, or if I can send the remotes even more often for smoother visuals. Only a single CFrame is passed each time the remote is fired, but I want to make sure I have a good idea of how much performance weight these things have for future reference.

Some side notes that may be relevant;

  • Since this is a purely cosmetic effect non-integral to gameplay, the remote used is an UnreliableRemoteEvent.
  • An event was used over a function so as to not have the server script yield while waiting for a client to return their CurrentCamera’s CFrame.
  • The remote that controls the CFrameValues is only fired from the client to the server, never the other way around.
  • There is a single remote all players fire to, and the server sided script that modifies the CFrameValues has a debounce for each player. I am unsure if this could cause problems and if each Player should use their own instanced remote instead, or if doing that would be unnecessarily complicating things.
  • The only argument being passed through the remote (other than the Player whose client sent it, of course) is the CFrame of the workspace’s CurrentCamera.
  • When determining neck joint C1 values on the client side, the information used to determine the local player’s neck joint is taken directly from their current camera rather than the CValue instance, since it can be accessed directly on their respective client. The CFrameValues are only read when determining the target C1s of other player characters.
1 Like

1/30 or 1/60 is really enough, you can decrease to like 1/20 and interpolate the cframes on clients
also, batch the cframes, so if alot of heads move in one frame, send all the cframes and the players that moved their head, rather than per player

local moves = {}

moveHead.OnServerEvent:Connect(function(plr, cf)
    table.insert(moves, {plr, cf}    
end)

Heartbeat:Connect(function()
     if #moves == 0 then return end --// you can do batch sizes, so only 5k head movements are sent per frame
     moveHead:FireAllClients(moves)
end)

and on client interpolate as youw ould

If you want maximum performance, you should look into UnreliableRemoteEvents. They are many times faster than regular remote events, and are perfect for your use case.

Another option is that you only send the remote when the player has moved the head a certain amount from current position and then send that new position with the event to server.

The other players then locally tween the head from old position to new position making it look smooth. You can also make a magnitude check so players only do the tween if the player is close enough to see it.

This way no remotes are sent when the head is mainly still. Drawback of this is that very small movements will not be picked up by other players.

What happens if a player joins when someone else has moved their head? You would need to store players head cframes on server which is useless.

1/20 tick with client interpolation is better option

Then the joining player will get the update next time that other player move their head. It might not be critical to the system that every single head movement is replicated and to 100% accuracy.

thats the whole point, server is not in control when client will move the head, so its better to do tick based update