What is the order of OnChangedEvent vs OnRealtimeModelReplaced for clients joining room?
I’m having inconsistent behavior in a class that relies on OnModelReplaced functions happening before any OnChangedEvents fire. When the remote client is already in the room, this seems to consistently work, but when the remote client is joining with the existing object already in there it seems the OnChangedEvent is firing before the Replaced function. Is there any recommended workaround or a checkbox maybe I’m missing?
5 Replies
Hi @rj. 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 provided knowledge sources, the expected order is that
There is no checkbox or explicit setting to control this order, but following the recommended pattern above should resolve the inconsistency. If you continue to see change events firing before
- Synchronizing Custom Data: Creating a RealtimeComponent subclass - RealtimeComponent lifecycle ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
OnRealtimeModelReplaced()
should be called before any change events (such as OnChangedEvent
or property change events) fire. This is because Normcore's lifecycle is designed so that when a model is set or replaced, you have a chance to subscribe to events and initialize your component before any updates are processed.
From the documentation:
When aThis means you should subscribe to change events insideRealtimeComponent
is first created, it starts with no model. Normcore populates it once we have successfully connected to the server (or instantly, if we're already connected) and callsOnRealtimeModelReplaced()
to provide us with a copy of it.
...
We can register for an event from the model that will fire whenever it’s changed locally or by a remote client. We’ll use that to call our method...
— Synchronizing Custom Data: Creating a RealtimeComponent subclass
OnRealtimeModelReplaced()
, ensuring you only receive events after the model is set.
However, your observation suggests that in some cases (such as when a client joins late and the model already exists), a change event might fire before OnRealtimeModelReplaced()
is called. The documentation does not explicitly mention this edge case or provide a checkbox/setting to control this behavior.
Recommended Workaround:
- Always subscribe and unsubscribe to model events inside OnRealtimeModelReplaced()
, as shown in the official examples.
- In your event handler, add a guard clause to ensure the model and any required state are fully initialized before processing the event.
- If you need to process the initial state, do so directly in OnRealtimeModelReplaced()
after subscribing to events, rather than relying on the change event to fire for the initial value.
Example pattern:
This ensures your initialization logic always runs before any change events are processed, regardless of the order in which Unity or Normcore triggers them.
Summary:There is no checkbox or explicit setting to control this order, but following the recommended pattern above should resolve the inconsistency. If you continue to see change events firing before
OnRealtimeModelReplaced()
, it may be worth reporting as a bug or seeking further clarification from the Normcore team, as the intended lifecycle is for OnRealtimeModelReplaced()
to be called first.
References:- Synchronizing Custom Data: Creating a RealtimeComponent subclass - RealtimeComponent lifecycle ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
<@446432643115122688> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
That goes into my second theory - the on changed events are firing during the model replaced function while subscribing somehow? Maybe not, again maybe I'm missing something obvious setup wise, but this is driving me wild
on change events only fire after a model is set and they don’t fire for the initial model setup
also if they fired before OnRealtimeModelReplaced, in theory it would be impossible for your code to know because you wouldn’t have had a chance to subscribe to the events yet
If you join a room, you will not receive any change events until your client modifies a model or a client modifies a model after you joined
Alright that’s good to know, thank you! I think I found a workaround for now