How can I have a singleton custom Realtime Component in scene
I have an instance of a custom Realtime Component syncing data over the network. Here's what I want:
1- When first client connects, it instantiates the Component's model to an initial data state.
2 - When the second client connects, it should detect that the same Component's model's was already instantiated with a default state by the first client, so this second client only has to replicate the state on the scene.
I've done experiments with the
isFreshModel
flag inside the OnRealtimeModelReplaced
function but, for the second client it seems to be called twice, once when it first connects, and has a default valued currentModel
. And then a second time, when it gets the actual data set by the first client. This behaviour seems odd, I would expect the currentModel
have the data set up by the first client filled in on the first OnRealtimeModelReplaced
call.
Am I thinking of the sync model lifecycle wrong?
How can I accomplish the desired behaviour described above?4 Replies
Hi @RoyNexus. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
Based on the information provided in the knowledge sources, the
OnRealtimeModelReplaced
method is called when a RealtimeComponent
is first created and it starts with no model. Normcore populates it once we have successfully connected to the server (or instantly, if we're already connected) and calls OnRealtimeModelReplaced()
to provide us with a copy of it. If this RealtimeComponent
was previously mapped to a different model (e.g., when switching rooms), it will provide a reference to the previous model in order to allow your component to unregister from events source (https://normcore.io/documentation/realtime/synchronizing-custom-data#creating-a-realtimecomponent-subclass).
The isFreshModel
flag is used to check if the model is a fresh one or an existing one. If it's fresh, you can populate it with the initial data state. If it's not fresh, it means the model already exists and you can just replicate the state on the scene source (https://normcore.io/documentation/realtime/realtimecomponent#using-a-model).
As for the OnRealtimeModelReplaced
being called twice for the second client, it might be due to the fact that when the second client connects, the RealtimeComponent
starts with no model and then gets populated with the actual data set by the first client. This could explain why OnRealtimeModelReplaced
is called twice.
To accomplish the desired behavior, you could add a check in the OnRealtimeModelReplaced
method to see if the currentModel
is null or has default values. If it does, you can skip the rest of the method. This way, the method will only run once when the actual data set by the first client is received.
Here's a simple example of how you could implement this:
Please note that HasDefaultValues
is a hypothetical method and you would need to implement a way to check if the currentModel
has default values or not.
Remember to also unregister from events of the previous model to avoid memory leaks and unexpected behavior:
I hope this helps! Let me know if you have any other questions.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@362795742198235136> kapa.ai is still learning and improving, please let us know how it did by reacting below
the only way you'll get 2 isFreshModel flags is if 2 instances of the model exists in the scene
the solution is to use a scene view model instead of instantiating it
you’re going to get it twice for things in the scene if they’re not the first to join. A model is put in place before you connect, and if you’re the first to connect, your model is added to the datastore, but if you’re the second to connect, your model is replaced (this is the second call you’re seeing) with the one that’s already in the datastore.
However that second one shouldn’t have isFreshModel set to true. If you’re seeing that, make sure you have at least one model property on the model.