You can definitely make your own reliable UDP remote events, just have to code the handshake yourself.
I am unsure of any latency penalties of doing this, though, but this is basically what those other network frameworks do, its just a layer on top of UDP.
Is there any point in doing this when TCP exists if it’s to mimick the exact same behavior ? How can this possibly be more profitable in any ways (cost, maintenance or just computing time) ?
A property was considered during the exploration phase, but ultimately considered subpar.
One factor against it is that we cannot really let you set this behavior at runtime. It opens up a large number of confusing and unintuitive edge cases. We have to have defined answers for them, because if we hand-waive it as unspecified, then whatever it is will end up being something we can’t change.
There are a few alternatives there but none of them are pretty. For example, we can limit setting the property until it’s in the data model, but as a rule we don’t like when property setting errors. So we could’ve made it a method (:SetReliability, which errors), but it’s not intuitive and also isn’t a lovely precedent.
Furthermore, the internal code complexity of it just isn’t great either since it becomes trickier to know what kind of reliability we’re expecting.
Yes, UDP would take half the time that TCP takes. Doing a reliability wrapper around UDP is no different, its just making sure the packet actually gets received. You get the best of both worlds. Also, if a packet gets lost in TCP, basically everything is frozen until that lost packet is resent. UDP does not have this issue
As for compression, at the very least it gets rid of the overhead of various data types since you would be doing the work of serializing the data for the engine knowing better how your data structure looks like so you wouldn’t need to waste bytes to define what the next X bytes should be read as and allows you to use less bytes if you don’t need the precision of the Double-precision floating-point format or know that the variables you are serializing is an integer within a certain value range.
A number sent directly via a remote event would use up 9 bytes since it would be sent as a FP64 with 1 byte of overhead which defines the remaining 8 bytes as a FP64
A number serialized as a double would use up 8 bytes as you would get rid of the overhead in exchange for a small amount of overhead from the string itself
A number serialized as a FP32 (which is what Vector3s use for example) would use up 4 bytes
A number serialized as a unsigned short integer would only accept integers in the range from 0 to 2^16-1 and would only use up 2 bytes
A number serialized as a signed byte would only accept integers in the range from -128 to 127 and only use up 1 byte
TCP takes a while because there IS that reliability and order wrapper with it. Making a TCP-like UDP with wrapper would result in the same, maybe worse performance as it’s not native. I don’t see how UDP with wrappers to act like TCP would be better in any ways.
Since nobody could provide an answer, I found one myself:
Yes, you can develop a protocol on UDP that simulates TCP. However, if you simulated TCP fully, it would technically have more overhead. Because TCP is implement as the packet and your simulated TCP is implemented in the body of the packet.
If you only need one or two features of TCP (such as basic ordering), then implementing it in UDP is useful.
Via StackOverflow. So there’s the answer, making full TCP out of UDP makes no sense unless you’re only using very few TCP-like features that would actually outweigh the cost of processing time and weights added to UDP caused by adding those extra layers.
A lot of the replies I got on my comments were very disjointed and sometimes didn’t even address what I said before, please remember to read the full thread before replying.
In a way… kind of. Rather the math.random() is built into the real world! When you send a message over a wire or wireless connection there’s a random chance it will get corrupted by noise or interrupted by other messages.
Normally with a RemoteEvent the engine does extra work for you to automatically re-send in the case where a message got lost, but that comes at the cost of extra latency. With an UnreliableRemoteEvent there is no automatic handling so you have to deal with potential unreliability, but in return you get lower latency.
If I am not mistaken, this should provide better performance and less latency/lag at the cost of being unreliable.
This remote event IS NOT intended to be an replacement for your weapons firing, button presses or player interaction.
This type remote event is what you would use for systems that make use of a buffer or where data is constantly being send over but there is no need for all data to arrive.
This type of remote event is what you would use for custom player movement.
The server does not need to know every move a player makes, when the game is experiencing lag, data is going to get dropped / lost to free up space and you predict player movement to compensate for that.
99% of the time you will not need and shouldn’t use this.
It’s usecases are very niche and specific but extremely useful for people who know what it’s good for.
Best uses would be constantly updating player position, Arm positions, Head position and other things that are constantly updated but have no crustal Impact on gameplay.
Unreliable events cost less bandwidth so they are best used for that.
In all seriousness, this will be a very very small yet hugely impactful feature that will make it much easier to improve performance. Small things with large impacts are my favorite!
I really wish these had an event for packets being dropped. That way developers can choose to fire it again, which would effectively make it a regular remote event but without pausing networking if a packet gets dropped.
Also that 900 byte limit is a massive bottleneck for rollback netcode. I can’t really use this to fire game states to the client, only commands. I COULD technically split state replication up into multiple remote calls, but roblox lacks some fundamental features to make this efficient such as a way to figure out how many bytes a payload has prior to firing it.
Fun fact, this isn’t actually possible to include!
The only way to ensure reliable communications is the recipient sending an acknowledgement back to the sender when they get the message. If the sender gets no such acknowledgement they will eventually try resending the message. The longer the sender waits without getting an acknowledgement the more certain they become that the message was dropped, but there’s no particularly good point in time to say “now I know it was lost” and fire the event.