fojam
fojam4mo ago

Best way to support async room loading?

Lately we've been working on a feature to support faster loading of normcore rooms, so that we can split larger areas over multiple rooms and load/unload them as needed. I made an object pool to reduce Instantiations on the initial room load, and we preload the pool with the total number of RealtimeView instances in the room (we keep track of these on the "host" client). However, even doing this, there's a significant bit of lag when loading in the room (about 845ms with 6 players, testing with roughly 1800 RealtimeModels in the room. This is the higher end of the possible object count though. 240 objects would be more typical for 6 players). We have a lot of small networked objects in the room per player, so it's difficult to improve this by reducing realtime model instances, since they all have properties that need to be networked individually. What we've tried: - preload pooled object instances - pre-activate the pooled objects and move them off-screen - override CreateModel and "preload" the model (found out this needs to be done on the prefab and not the instance) - reduce time in OnRealtimeModelReplaced calls (still working on this) Are there any other ways we could go about reducing this?
6 Replies
kapa.ai
kapa.ai4mo ago
Hi @fojam. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Hmm, I don't know enough to give you a confident answer yet. However, based on the information provided in the knowledge sources, there are a few things you could consider: 1. Optimize your RealtimeModel: As per the RealtimeModel documentation (https://normcore.io/documentation/room/realtimemodel), each field in your model should be a primitive type and designed to synchronize data that can be easily serialized and transmitted to other clients. It's not possible to store a complex object, such as a Material or Texture, in a model. You'll need to pick out the pieces of data you would like to synchronize and use a RealtimeModel to synchronize them. Attempting to synchronize every public property of such an object would require too much bandwidth to do correctly, and in most cases, the values do not change very often. 2. Use Normcore's Instantiate API: According to the RealtimeComponent's model documentation (https://normcore.io/documentation/realtime/common-questions#why-would-a-realtimecomponents-model-remain-null), if the model was instantiated with Unity’s Instantiate API (Instantiate() or GameObject.Instantiate()) instead of Normcore’s Realtime.Instantiate(), it could cause issues. Make sure to call Realtime.Instantiate(prefabName). 3. Split large spaces across multiple Normcore rooms: As mentioned in the Room Server Options documentation (https://normcore.io/documentation/room/room-server-options#how-many-players-can-i-fit-in-a-single-room), for extreme cases, you can split large spaces across multiple Normcore rooms, or you can use Normcore Private, which supports even larger room servers. 4. Ensure proper usage of RealtimeView: As per the RealtimeView documentation (https://normcore.io/documentation/realtime/realtimeview), when a prefab is instantiated, RealtimeView creates a model for each RealtimeComponent on the prefab and puts it into the datastore. Then, when the prefab is instantiated on other clients, RealtimeView will connect the model in the datastore with its respective RealtimeComponent on the prefab. Remember, these are just suggestions based on the information provided in the knowledge sources. You might want to reach out to the Normcore team for more specific advice tailored to your use case. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4mo ago
<@119985475967516673> kapa.ai is still learning and improving, please let us know how it did by reacting below
fojam
fojam4mo ago
There were also some potential places I saw where Realtime could load in the initial update faster: - LoadRealtimePrefab is called once for each spawned object (during RealtimeViewModel.CreateComponentsModelAndChildViewsModelIfNeeded), which introduces atleast 1 extra string comparison per instantiated object. Since the view is an instantiated RealtimeView, it should already have the serialized parent-child hierarchy for the prefab available on the view, so it shouldn't need to get the prefab. (I could see how this might be due to the whole component/model separation though) - The initial "Read" of the RealtimeModels could happen on a background thread asynchronously, since it's only dealing with raw data that hasn't been passed to the user via callbacks yet (and it's not using any unity objects, so it doesn't need to stay on the main thread)
maxweisel
maxweisel4mo ago
This is one we've been investigating for a bit. Unfortunately, due to how our events work on models, we're essentially blocked on rewriting our serialization system under the hood. That said, do you have a profiler snapshot or something we can take a look at? Maybe there's another spot we can optimize for your use case.
fojam
fojam4mo ago
Yeah definitely! The deep/non-deep profiler snapshots are both pretty huge though so am uploading to google drive. Is it fine if I share them in a DM once they're up?
maxweisel
maxweisel4mo ago
yeah that's perfect