RunService.NetworkStepped Event

Works like RenderStepped except it’s linked to the network. It would fire each time network data is sent out. The reason I want this is because I have custom characters that I’m replicating the positions of. In order to replicate their updates I have to send the information to the server through a remoteevent. This is a problem because if I send an update every time the position updates then I’ll be sending 60/20=3 times more data than is necessary.

The obvious solution is to only send updates through the remote at an interval of 0.05s, right? Wrong. Because wait() is not synced to the network step, I can end up with up to 50ms unnecessary delay.

Thoughts?

109 Likes

That would be cool, and I could imagine it client side for receiving a packet, but if you were to run it server side, how would it work? Are all the packets all in sync or does it do like a wait() per player, making it out of sync?

3 Likes

This is for syncing with sending, not receiving.

4 Likes

And in the case of RenderStepped being executed in Play solo (perhaps from a module that uses HttpService) it’d be useful to have RenderStepped work as this rather than just error.

2 Likes

I was in the middle of writing a post suggesting this exact feature (same name and everything) and this fancy new forum conveniently told me about this post.

This would be extremely useful.

4 Likes

pls

20 Likes

Would love to have an event like this, very much needed.

1 Like

I would also use this. Support.

3 Likes

This is a much needed function.

4 Likes

I know it’s been a while, but unless I’ve missed some updates since 2015, this is still an incredibly important feature for developers to have. Fine-grain control over replication/networking is pivotal to making any decent FPS or racing game – really any game that is heavily contingent on user input, lots of moving objects, and time for that matter. Since outgoing replication doesn’t run every frame, and we have no precise way of running code immediately before and/or after an outgoing replication step, the current situation is pretty suboptimal. No matter how we approach custom replication, we will always run into a subset of the following issues: the event queue overflowing on the receiving end, queueing up unnecessary amounts of data on the sending end (as well as the timed wasted computing it), the possible extra time delay Sharksie mentioned, etc.

It’s also probably worth noting that there are quite a few games currently in development that would benefit tremendously if this feature were added. That being said, please please please please please, pretty please implement this! Based off of what info I can get about the task scheduler and the nature of the RunService events that already exists, I can’t possibly see this being difficult to add. It needs to happen!

29 Likes

I was able to communicate with a Roblox network engineer as part of the Spring 2021 Accelerator. Roblox will replicate any remote calls at the end of the frame in which they were made (or the beginning or the next, depending on how you want to think about it) up to a per-server-client-connection bandwidth limit. I don’t remember what that limit is, but, regardless, this feature request isn’t necessary.

Hopefully this helps anybody who still has to search the forum for info on this topic. Roblox doesn’t publicly document this.

7 Likes

Thanks for your post, but you seem to have misunderstood what the engineer was talking about.

On servers there is no universally distinct “frame”. There are lua frames and network frames (there are other frames too but these two are the only ones relevant to this post). Lua frames fire, at the most, 30 times per second. Network frames fire, at the most, 20 times per second. These frames are, by design, not synchronized. The proposed event allows developers to synchronize their code execution with the network step. Synchronizing code with the network step this way allows developers to avoid sending redundant data when the lua step fires twice during the same network step.

4 Likes

The engineer explicitly said that the network output step is not capped at 20 Hz. It occurs every frame, where, by “frame”, I mean a single unit of the RunService events Roblox exposes to us: RenderStepped, Stepped, Heartbeat. Those events maintain a set order and are capped at 60 Hz for players without FPS unlockers. Players with FPS unlockers can run a game instance in which that frequency is only limited by their hardware.

I was vague in my post, and I may have been given incorrect information, but there was no misunderstanding.

It looks like you’re correct on the point that network step is no longer 20 hz, but you are incorrect about it being synchronized.

Here I’ve set up a script that fires a remote event every heartbeat. A client receives the event and outputs the time between the current receive and the previous receive.

You can clearly see that it does run at 60hz, but you can also clearly see that there are mistimed receives. This happens either because the server is stepping lua multiple times during one network step, or because the client isn’t processing the events at the correct intervals. Either way, this is a network data redundancy problem that needs to be solved.

You are mistaking the call of a remote event script signal with the network ingress step. Both the network ingress and egress step fire once per frame (where “frame” is as I defined it in my previous post). During the network ingress step, any remote calls that have been received and can be acted on at that time are dispatched with the OnServerEvent or OnClientEvent script signals. There may be multiple remote calls that meet these criteria on any given frame due to network unreliability/randomness.

But what do I mean by “can be acted on” ? Roblox implements a per-server-client connection reliability and orderedness protocols for remotes. On a conceptual level, this means that any remote calls you make are guaranteed to arrive at their destination (barring any termination of client-server connection due to a player leaving the game or what have you) and to be dispatched at their destination in the exact order in which they were called at their origin. On a more technical level, this requires the following implementations: acknowledgment messages to ensure reliability, headers appended to remote call packets encoding order (as well as the relevant remote instance), and buffering on the receiving end to cache remote calls prior to the ingress step and prior to any remote calls which were sent before them arriving. Hence, by “can be acted on,” I mean that, given server/client A and server/client B and the sequence of calls from A to B denoted by call_AB1, …, call_ABn, then call_ABi can be acted on only if i is 1 or call_AB(i-1) has been dispatched.

Hence, because of the inherent unreliability/randomness of networking, put together with roblox’s remote protocols, you can imagine why you’re getting those receive intervals. The reliability and orderedness protocols create a real issue for developers who need to send network data at 60 Hz or somewhere near that rate. One packet may get lost and hold up those following it for an intolerable amount of time. And devs, depending on their use case, may be better off discarding such packets, especially if they need near 60 Hz state replication.

The Networked Stepped event would only be necessary if outgoing remote event calls were sent a rate below the framerate (where “frame” is as I defined it in my previous post). They are not sent below the framerate, and hence you do not have to worry about sending duplicate data nor sending data at an insufficient rate (60 Hz is solid).

The essential networking feature request is that roblox allows us to opt out of reliability and orderedness. These protocols being forced is the one and only outstanding issue I can think of with respect to roblox networking. Any others (like multiple OnClient/OnServerEvent invokations per frame) ought to be fixed by developer implementations on a per-use case basis.

I hope this is helpful for you and anyone else who comes across it. My only goal in coming back to this thread was to provide info for everyone who, when trying to learn the roblox networking particulars relevant to them, resorts to sifting through the dev forum where just about everybody else is in the dark because the official documentation is awful. That’s why I was so heavy with the details. I’m not trying to win a “who knows more” contest or anything, so please don’t take it that way.

10 Likes