Re-subscribing to delegate events on scene change
Hey yall, my app systemetically changes the scene of all clients in a given order. The first time this happens (from scene A->B) it works great. However, after that (B->C etc), my delegate event (IsSceneChangingDidChange) does not fire.
I can also see that the OnRealtimeModelReplaced() method does not run again. I'm not sure how to manually resubscribe to this delegate to listen for model changes when a new scene is loaded. My RealtimeView component this script is attached to is persistent and a singleton.
Here is the method in question:
protected override void OnRealtimeModelReplaced(SceneSyncModel previousModel, SceneSyncModel currentModel)
{
if (previousModel != null)
{
// Unregister from events
previousModel.isSceneChangingDidChange -= IsSceneChangingDidChange;
}
if (currentModel != null)
{
if (currentModel.isFreshModel)
{
currentModel.nextScene = nextScene;
}
// Set local variables based on model
nextScene = model.nextScene;
currentModel.isSceneChangingDidChange += IsSceneChangingDidChange;
}
}
Thanks in advance!14 Replies
Hi @NeuroGoblin. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
----------------------
The
OnRealtimeModelReplaced()
method is called when a RealtimeComponent
is first created and successfully connected to the server, or instantly if it's already connected. It provides a copy of the model and if the RealtimeComponent
was previously mapped to a different model (e.g., when switching rooms), it provides a reference to the previous model to allow your component to unregister from events source (https://normcore.io/documentation/realtime/synchronizing-custom-data#creating-a-realtimecomponent-subclass).
In your case, if OnRealtimeModelReplaced()
is not being called again when you switch from scene B to C, it might be because the RealtimeComponent
is not being recreated or reconnected to the server. This could happen if the RealtimeComponent
is attached to a GameObject that is not destroyed when loading a new scene.
One way to ensure that OnRealtimeModelReplaced()
is called again is to manually destroy and recreate the RealtimeComponent
when loading a new scene. However, this might not be the best solution depending on your specific use case.
Another possible solution is to manually call OnRealtimeModelReplaced()
when a new scene is loaded. You can do this by subscribing to a scene loaded event in Unity and then calling OnRealtimeModelReplaced()
with the appropriate arguments.
However, please note that these are general suggestions and might not work perfectly in your specific case. It's recommended to thoroughly test any changes to ensure they work as expected.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@196555254496493568> kapa.ai is still learning and improving, please let us know how it did by reacting below
@Normcore Assistant if I manually call OnRealtimeModelReplaced() on scene load, how can i supply it with the correct parameters of SceneSyncModel previousModel, SceneSyncModel currentMode ?
Let me check the knowledge base for you. One moment! :books:
----------------------
The
OnRealtimeModelReplaced()
method takes two parameters: previousModel
and currentModel
. These are instances of your RealtimeComponent
's model class (SceneSyncModel
in your case).
The previousModel
is the model that was previously associated with your RealtimeComponent
, and currentModel
is the new model that is now associated with it.
In the context of your application, you would need to keep track of the current and previous models. You could store the current model in a variable every time you create or update it. Then, when you're about to create or update the model again, you can use the stored model as the previousModel
and the new model as the currentModel
.
Here's a basic example of how you might do this:
In this example, UpdateModel()
is a method you would call whenever you want to update the model. You would pass the new model as a parameter to this method.
Please note that this is a simplified example and might not cover all edge cases. You should adapt this to fit the specific needs and structure of your application.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@196555254496493568> kapa.ai is still learning and improving, please let us know how it did by reacting below
If anyone else has a response That'd be awesome !
if this is a persistent model then you don't need to register again on scene change
you could try changing the scene change property to an int instead of a bool, that way you can keep triggering it by incrementing the int because by default no message is sent if the model hasn't been changed (for instance changing a true to a true)
hmm okay that makes sense - alternatively i could make sure the bool is set to false onsceneloaded?
you could also set the skip equality check parameter in the model property
or you could add a check for scenemanager.active scene against the scene name property to check you are in the same scene
good for late joiners
Thanks @Mechabit - incrementing the int worked well
for some reason i could init the bool to false but it didn't want to fire delegate changes after that
even after explicitly toggling true / false
odd
the int method works more generally if multiple people access it
I've got one questions @NeuroGoblin, why do you require a room with Persistence? Is it (case A) because of scene changes and you need to preserve data when changing scenes or (case B) do you need it stored "forever" for future connections to the room? I'm asking because if it's the case A, I had that in my project - an escape room with 3 chapters and players progression from chapter 1 through 3. I discussed that here and it's better to have a separate Realtime instance connected to a "session room" where all users are connected to it and the connection is continued when scene changes - so .e.g. you can keep voice chat active when scenes change. I'll try to search where I discussed that so you can check how this case matches yours.
Hey @Michał Wróblewski , thanks for the question - Essentially the setup here is to have an 'Admin' room (and corresponding Realtime component) that persists through all scenes and all clients remain connected to. The purpose of this is to send global events such as synchronised scene changes, notification messages, etc.
As the users progress through the experience, they will then connect to additional rooms where they can see other players' avatars, etc (this part has already been built). I believe my current Admin setup is the same as the last part of your message, where there is a separate instance (AdminRealtime) that persists through all scenes, and then players simply connect to RoomA, RoomB etc as they progress, to sync the showing of avatars, etc.
All good then, it wasn't clear but I felt similar vibes - good choice anyway and good luck