From an efficiency/effectiveness/NOT convenience standpoint, are ObjectValues better than passing data through remotes?

Assuming convenience/readability doesn’t matter, is it better to use ObjectTypeValues or remotes?
Scenarios:

  1. only one player needs the data LIVE
  2. everyone needs the data LIVE
  3. only one player needs data that can be updated in intervals and in bulk (not live)
  4. everyone needs data that can be updated in intervals and in bulk (not live)
  5. any other scenarios you can think of
2 Likes

I’m guessing you mean “[Type]Values” and not “ObjectValues”? Most of the data that you want to send to the client isn’t Roblox instances.

In a way you’re right. I think that people do actually use Remotes in some cases where they could just be using a [Type]Value object. The upside to doing this is that you don’t need a separate “Initial Get” / “Update” for the data in your Remotes—the [Type]Value object handles both at the same time.

The main disadvantage of trying to use [Type]Value objects for replication is that as soon as you start building a reasonably complicated game, your data structures that need to be sent to the clients become more complicated than a simple Number or Bool, and then it becomes really cumbersome, or even impossible, to try to pass them through [Type]Value objects. You can try to use multiple [Type]Value objects, but that starts running into huge atomicity issues (Each change is replicated separately, even if they’re really all part of the same “send” conceptually). You could shove things through a StringValue with your own serialization… but at that point why aren’t you just using proper Remotes?

And using a [Type]Value object isn’t forwards compatible in that case either: Once you decide that you do need to attach more information to what was once a single Number or Bool piece of information, now you need to rip out that [Type]Value object and replace it with a proper Remote, when you could have just used a Remote in the first place.

TL;DR: I think that there are legitimate cases where using a [Type]Value is better than using a Remote, but you should make sure that you’re not going to need to send more data attached to that value later before you do.

7 Likes

You’re right, I meant to say type and not object values, but what about from an efficiency (not convenience) standpoint?

Chances are your game is much more latency bound than network bandwidth bound in the first place, so it would make absolutely no difference which takes more bandwidth (“efficiency”). And even if your game is network bandwidth bound, chances are the things that are bottlenecking the bandwidth are giant data strings that you’re sending and not a ton of small single-value replications, so it still doesn’t matter in that case. So really it doesn’t matter which is more “efficient” in the end.

From a convenience standpoint… isn’t that exactly what my last reply was talking about?

1 Like

I’m not really interested in a convenience standpoint, thats why I have the “not” in front of it xd

Also I’m just wondering to learn more, I’m not experiencing any issues or anything wither either of them.

I’m not really interested in a convenience standpoint, thats why I have the “not” in front of it xd

Sorry for the reading fail.

I don’t think that anyone here can tell you 100% for sure which is technically more efficient in what case other than the developers working on the networking code.

There’s a ton of complicated batching / timing / dependency logic in the Roblox networking code, so it’s not as easy as testing which is faster in some simple test cases in local test. You would really have to set up two copies of a non-trivial place using both approaches and somehow collect some statistics, because you would need real usage patterns to see which actualy performs better after all the magic that the Roblox networking code applies.

1 Like

For the simplest case where you’re updating a single value (number, bool, string) and you want all clients to be in sync, there is probably negligible difference. But as soon as you want to send either a complex data structure, or send different values to different players, the RemoteEvent is the going to come out ahead in performance and code elegance over a collection of value objects. Even if the message structure already exists as pre-created value objects in ReplicatedStorage or the Workspace, it’s still going to be more steps to respond to a change to one of them (e.g. a master value) and then loop over all the rest reading their values than to just use values passed in a RemoteEvent.

Consider also that if you want to send a multi-valued state from say, server to client, then you also need to worry about consistency of the state because value objects will replicate independently, you can’t do atomic read/write across a bunch of value objects. You could do something horribly inefficient like creating a versioned set of value objects for each state, but of course you should not.

5 Likes

Fairly recently I wrote a module that allows me to create networked tables. The objects are created on the server and can then be shared with individual clients while the tables themselves are kept in sync. As a bonus it also supports custom filtering so the client is able to set certain values if the server permits it, which is really useful in some cases.

2 Likes

I actually use Number/StringValues rather than remotes for passing players their save files. Because I don’t want to have to send the player’s entire save file every time its updated(new money/XP/item owning, etc, my account is 31,776 in string length for example, not a small amount to send out frequently), when just changing/instancing a single value will do.

Late bump, but there is one important difference between remotes and Value objects. Value objects are replicated as properties, versus the remotes which are replicated as events.

The network replicator only sends data at about roughly ~20 Hz. For properties we queue sending a changed event when the value changes only if there’s not already a changed event in the queue. If the property changes again while that’s still in the replication queue we update the existing changed event in the queue and do not queue any new events. Values replicated as properties will skip sending intermediate values between replication steps.

For a value that you change every frame (specifically from the server; Values on the client never replicate back because of FilteringEnabled) this may be a win. It will send as fast as the replication system allows, and it won’t waste data on intermediate values you’ll receive late and probably batched with other updates that would immediately overwrite it.

If intermediate values are important you need to use remotes. Remotes are usually what you want in general, but but this difference between replicated properties and events might make Value objects better suited for some rare server-to-client cases where intermediate values don’t matter.

25 Likes

This might be a little off topic from this post, but it relates to your difference in behavior explanation:
Say I have my own custom value-like instance that uses remotes to handle replication, is there any way to make this behave in the same way as Roblox value instances (specifically from sender’s side to only send the most recent value because pruning from the receivers end is e.e)? I would think you need to perform the FireClient/FireServer calls at a fixed rate and only if a change from the value read at the last step is noticed. This could run on heartbeat(well a 20hz version of heartbeat), but it would be better to time it to run right before replication. So is there any way to run something right before network replication? (xd this last part is basically asking the question in this thread Calling remotes right before network replication)

Something like a ReplicationStepped would almost let you do this, but not quite. We don’t support this currently.

There’s several extra complications. Like the replicator doesn’t always finish sending the full queue every step if the queue is large, especially during game join. Even if you could run Lua right before we started writing actual packets we couldn’t guarantee your event would actually be sent in that step or tell you when it will be sent at all. We can only consistently guarantee that it will be sent eventually.

1 Like

Apologies for the 3 year necro-bump!
I’m assuming this is the case but I just wanted to confirm; do Attributes have the same replication behavior as Values? For the most part it seems that developers might be better off using Attributes over Value objects now for communicating over an “unreliable” channel (from my understanding an “unreliable” channel seems to be the same as your explanation for replication that skips sending intermediate values between replication steps)

2 Likes

Attributes are replicated in a similar way to properties meaning only the most recent value is sent each network step.

In the future I’d recommend creating a new post for your question as it avoids necro-bumping and potentially makes it easier for others to find the same answer.

4 Likes