Custom replication via Zones/Scenes

As a Roblox developer, it is currently too hard to replicate or not replicate things to certain clients. As Roblox games grow larger in scope, size, and complexity, a lot of developers have been itching for a way to load & unload instances/models/folders to specified clients to save memory, client bandwidth, and create more immersive games. Something like this has been proposed multiple times before, but now the need for it is greater than ever, and I want to draw attention to it in the best way I can.

The suggested functionality below is similar to room/zone/scene systems found in almost any game development platform. Roblox does not have anything similar.

For a simpler solution that might cover this problem, this feature request thread exists. I’m posting this to address certain difficulties & try to create a solution with quality-of-life improvements on top of better replication choices.

Roadblocks & Issues
Currently, these are the options we’re stuck using for custom replication:

  • Clone in things completely locally- This works fine for client-side objects that only the player can interact with, but this leaves the server completely out of the question. For more important things like obstacles or collectibles, this can cause security issues down the road. It’s important for the server to be able to see some things, but as Roblox games grow bigger, we don’t want everything to be loaded in for all clients at once.
  • Delete unwanted areas/objects from the client- Unfortunately, this method eats up memory. You can remove a serverside object from the client but it will continue to affect performance. This is also a hacky method we shouldn’t have to use.
  • Teleport players to other places in the game- This method splits up players from their friends, decreases retention, can lead to unexpected disconnects or data problems, and also creates issues when developing due to having to swap between several Studio files to update your game in any capacity, which leads to a very stunted workflow.
  • Clone things from the server into PlayerGui - This is the closest way to emulate the desired behavior, but it’s obviously a hack, and leads to issues like memory leaks if not done in a very specific way. Having to do this to replicate something to both the server & a specified client is just not good at all.
  • Streaming- Streaming is not a viable option, which is why it’s very rarely used, despite its improvements since being released. There is absolutely no customization with Roblox’s streaming and it does not solve the solution of loading/unloading objects and areas properly.

New Service Proposal

Here’s what I’m proposing - a new service that can handle loading/unloading “zones” or “scenes” to clients from the server, maybe called SceneService or ZoneService. I’m thinking about it similarly to the way CollectionService is structured because it’s one of Roblox’s most useful & user-friendly services for developers currently. As it stands, these functions/events could also simply be added to an existing service such as ReplicatedStorage or something. I’m not an engineer, so suggestions for different ways to approach this problem are very welcome!

Functions

  • :CreateScene(String name)
    Creates a new scene with the given name. Scenes do nothing until tied to instances.
  • :AddToScene(String scene, Instance object)
    Adds the given Instance to the scene. This can include anything as long as it’s visible by the server and exists within a service that isn’t serverside-only (ex Workspace, ReplicatedStorage). When an object is tied to a scene, it will only be seen by the server until its attached scene is loaded to a client via :LoadScene().
  • :RemoveFromScene(String scene, Instance object)
    If the instance is part of the scene, removes it from the scene, treating it as a normally replicated instance instead.
  • :LoadScene(String scene, Instance player,)
    Only available on the server. Replicates the named scene to the specified client. Players can have multiple Scenes loaded at once.
  • :UnloadScene(String scene, Instance player)
    Only available on the server. Unloads a scene to the given client, effectively unloading it to the player but keeping it in existence on the server and to other clients who may still have the scene loaded.
  • :GetLoadedScenes(Instance player)
    Can be used from the server or client to check which scenes the specified player currently has loaded. This could be used to update lighting & ambiance depending on the player’s current scenes or hide other player characters that aren’t in the same scene as the client (just as a couple examples).
  • :GetScenes()
    Returns a table of all scenes currently in the game.

Events

  • .SceneLoaded(String scene)
    Fires when a scene is loaded on the client. Can be used to handle clientside object code within the scene.
  • .SceneUnloaded(String scene)
    Fires when a scene is unloaded on the client.

Use Case Examples

  • Big Games with lots of levels & expansive, immersive worlds - With custom scenes, we’d finally be able to have characters move between levels without loading in huge folders/models to the entire server or using hacky methods discussed near the top of this thread. Almost any major game engine has some way to move a player between areas and unload anything that isn’t necessary to the client, while keeping the levels stored on the server where they don’t impact client memory.
  • Unload characters in other areas to save on networking
  • Load specified areas and objects without having to worry about streaming making half the level disappear or mess up local scripts
  • Unload distant areas so players only see what’s intended by the developer
  • Add immersive sound & lighting depending on the player’s area without having to create extensive custom lighting/ambiance zone systems yourself
  • Organize your game’s worlds to trim the fat of memory/networking

This feature or something similar has been requested for a long time. I personally know multiple developers who requested it at HQ, myself included, and have seen suggestions come and go without being added for multiple years. I hope that this is extensive enough to be considered! Please feel free to reply with any ideas or suggestions. We can possibly workshop this into something that would make creating massive & interesting Roblox games significantly better.

236 Likes

Quickly looking over it, yeah, I think this is pretty much a must-have for Roblox continuing into the future. All for it.

28 Likes

I recently made a post about a similar topic, but less about scenes and more about specific objects and properties. Check it out here:

You’ve gone into a lot more detail with it, and I’m in full support of this. There is no reason why developers shouldn’t have full control over what replicates and what doesn’t in their games. Something as fundamental as this should always be in the developer’s control.

Brilliant post, I really hope Roblox do something about this soon. There are a lot of use cases for this kind of thing (mainly performance+bandwidth cases) which could make the games in Roblox potentially so much bigger.

10 Likes

Interesting idea, I’m all for it.

:RemoveScene(String scene) is missing, also (may not be appropriate but) a more specific :GetScene(String scene).

I’m thinking some OOP might be better for this, as the system may end up being a bit more complex than CollectionService. You’d have a Scene class that handles loading, unloading, add-to and remove-from that gets returned from :CreateScene() and :GetScene(). This would lower the number of methods and signals on the main service object, allow for expansion of the Scene class to have more features and would separate scenes more cleanly from the service. Think TweenService + CollectionService.

12 Likes

As a developer, I have wanted to produce large train games for some time, routes that feel like they are the size of a whole county. The level of detail I want to include in the game limits the size of the map based on performance of existing large train games on Roblox. The technology to keep memory and framerate to manageable levels is something I don’t see floating around, so I will have to spend time developing it myself, using time I could be spending on adding content and polishing the game.

8 Likes

I think this is the direction Roblox should go for having huge universes, not the “Games” feature that is unreliable, limited, and makes devs less money.

I cannot tell you how many games I have wanted to make that would basically rely on such a feature. Imagine a space game where you can separate scenes for planets on the surface and from space, or an RPG where you can enter huge worlds and only have one loaded at once. All without leaving the server.

This feature would make it easier for devs (No need to create and maintain 50 “Game” places anymore) and would make players happy (You are always playing in the same server, maybe with friends). I can see 100-player games being much more viable with such a feature.

Even on a simple level, this would still benefit us so much. I think Roblox has to give us something like this eventually.

15 Likes

would appreciate this deeply. it would be neat if this could get a studio editor too cough Tiff cough

2 Likes

One of the biggest suggestions during the Accelerator Program was more control with streaming.

Hopefully they get around to doing this pretty soon

4 Likes

Thanks so much for the amount of detail you have provided in your request. I’ll be working on getting this filed today and will follow-up if I have any questions.

26 Likes

Yes!!!
I would be SO happy if this were to be a feature!!
The one thing I’m generally scared of while working on my game is that it would be slow even when I’m applying as minimal details as I possibly can, and it most likely won’t be a small map.

This would help a lot!

4 Likes

100 likes in a little over a month- I think it’s safe to say we’re all sore for a feature like this. Let’s try and keep the momentum up in January when the code freeze is over!

8 Likes

I have stumbled upon a situation where this feature would help me out a ton. Description of the situations as a use case for this feature.

2 Likes

Would be much easier if this existed.

4 Likes

The creativity which could be achieved with this system is unimaginable. We need this as creators now.

2 Likes

I like this, it would really help with massive open world environments, and provide more options to help big servers run more optimally. Dividing server / client workload is extremely essential in game development and I think this feature request would help devs do a lot with that. Also could someone please tell me why StreamingEnabled doesn’t work based on CurrentCamera Cframe and instead works off Torso position like fr how u supposed to get a cutscene in smh

An idea to possibly improve this is to have LOD zones just like you’d have the current zone. The game dev would need to make 2 levels per zone, but it would be optional and allow for farther draw distances. This could be very imperative towards making massive open worlds in roblox.

3 Likes

A potential (ab)use case of this feature is a surefire way to cloak enemies in combat and prevent hackers from determining cloaked player positions (can’t make visible parts that aren’t there):

  • all characters are assigned unique replication zones
  • characters of team players are replicated to each other
  • when an enemy character is uncloaked, it is replicated to all team players
  • when an enemy character is cloaked, it stops replicating to team players

Another use case:

Consider a space game that is set in an asteroid field of good size (e.g. 100,000 studs across) where asteroids are scattered across the entire map. The asteroids are not static, and can be manipulated by players. Players do not need to know about changes to asteroids that are 90,000 studs away from them, much less changes to 100 asteroids, none of which are larger than a single pixel.

Or in other words, StreamingEnabled that I control.

10 Likes

A note on this: If roblox ends up adding more control to StreamingEnabled in the form of adding replication Zones, it would make a lot of sense for devs to be able to choose a part (or a camera) that the streaming service uses as the center point. My game’s cutscenes don’t work if StreamingEnabled is turned on because the player hasn’t spawned and the camera is looping through a list of CFrames. If we could at least make StreamingEnabled work based on the camera position, or even just preload specific areas of the map, that would at least make the situation a lot better.

3 Likes

As it stands, and as it has stood for years, I really can’t see StreamingEnabled ever becoming this flexible or useful to developers. There are a lot of great examples in this thread of what people want to do to expand their games.

Considering how this is such a sore spot for a lot of creators here & how often it’s been suggested with no response other than the vagueness of “we’ll improve streaming” (which has certainly been improved, but functionally is the same as it was on release), I’m worried that for some reason or another they think a system like this wouldn’t be “user-friendly” and would rather have a checkbox that attempts to do everything for you without knowing what the developer’s intent is.

6 Likes

I think Roblox is slowly moving away from that mentality when it comes to developing. For instance, they removed the check boxes for bubble chat, thus giving us devs more control but also making it less simple to implement. FIB is highly customizable compared to the old lighting.

But that’s just a guess. I think the more control devs have, the better :slight_smile:

2 Likes

Support! Generally, I’d love to have more control over replication.

How would you feel about Scenes being actual userdata objects, so you would have something like:

local sc = Scene.new(workspace.Model1)
sc:Add(workspace.Model2)
game:GetService "SceneService":LoadScene(Player1, sc)

I think this approach would be more in-line with the typical OOP practices (correct me if I’m wrong). The reason why I think CollectionService works as it does is because Tags essentially are strings, so there’s no need to create a separate data type for them.

8 Likes