What's going on with offline mode?
I'm adding an offline mode to my application. It sounded simple enough to implement with Normcore's offline mode. So, I set the room connection options to offline, but now I'm running into some weird issues.
This error shows up from 0 to 4 times when I run my scene. When it doesn't show, elements of my project still fail. What's going on?
22 Replies
Hi @Harper. 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, I can offer some insights into your offline mode issue with Normcore.
The error message you're encountering suggests that there might be a timing issue with how the RealtimeView and its model are being initialized in offline mode. This error typically occurs when trying to access ownership information before the model is fully set up.
Here are a few points to consider:
1. Offline Mode Setup: Make sure you're setting up offline mode correctly. According to the Room > Offline Mode documentation, you should use the
ConnectOptions
struct when calling Connect()
:
2. Timing of Access: The error suggests you're trying to access the RealtimeView's ownership information too early. In offline mode, some behaviors might be slightly different. As per the documentation, "For the most part, all features in Normcore operate the same way as online mode. However, there are a few details that are different."
3. Initialization Order: Make sure you're not trying to access RealtimeView properties in Awake()
or too early in Start()
. According to the Realtime > Common Questions documentation, for scene RealtimeViews, you need to wait until realtime.connected == true
, or the didConnectToRoom
event has fired.
4. Serialization Events: The documentation mentions that "The serialization and deserialization mechanisms are skipped in offline mode. Change events will still fire, but serialization events like RealtimeModelEvent.OnWillWrite
will not be invoked."
To resolve this issue:
1. Ensure you're setting up offline mode correctly.
2. Delay any access to RealtimeView properties until after the connection is established.
3. Consider using the didConnectToRoom
event to trigger your initialization logic:
4. If you're still encountering issues, you might need to review how your custom RealtimeComponents are set up, especially if they rely on serialization events that don't fire in offline mode.
If these suggestions don't resolve your issue, you may need to provide more details about your specific implementation, as the knowledge sources don't contain enough information to diagnose the exact cause of your problem.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@276154194606424064> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@kapa.ai is it possible that this is happening because I often assume an empty model is fine before my client gets a real model? Maybe in offline mode there is no empty model provided before technically "connecting" to a real one.
Let me check the knowledge base for you again. One moment! :books:
----------------------
Your observation is quite insightful and likely correct. Based on the information provided in the knowledge sources, there are indeed differences in how models are initialized and handled in offline mode compared to online mode.
According to the Realtime > RealtimeComponent documentation, the lifecycle of views and components differs between scene objects and prefabs, and between online and offline modes. In a typical online scenario, Realtime creates an empty model for every view and component before connecting to a room. However, in offline mode, this process might be different.
The documentation states:
"When using views and components in a scene, they follow this cycle:
1.
Awake()
+ Start()
both run. RealtimeView registers with Realtime.
2. Realtime creates an empty model for every view and component and sets the model on each, triggering an OnRealtimeModelReplaced()
call.
3. When Realtime connects to a room, if an object in the scene doesn't exist, its model is inserted into the datastore. If the object already exists, Realtime creates a new RealtimeModel, populates it with the state from the server, and replaces the model again, triggering an OnRealtimeModelReplaced()
call."
In offline mode, step 2 might be skipped or handled differently, which could explain why you're not getting an empty model before "connecting" to a real one.
To address this, you should ensure that your code doesn't assume an empty model will always be available. Instead, you should wait for the OnRealtimeModelReplaced()
call before interacting with the model. Here's a recommended approach:
This approach ensures that you're only working with the model when it's actually available, whether you're in online or offline mode.
Additionally, the Room > Offline Mode documentation mentions some limitations and differences in offline mode, such as Realtime.clientID
always returning 0
and Realtime.roomTime
returning the device's system time. These differences might also contribute to the behavior you're observing.
If you continue to face issues after implementing these changes, you might need to review how your specific RealtimeComponents are structured and ensure they're compatible with both online and offline modes.
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------<@276154194606424064> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
offline mode connects instantly so try adding a couple frames delay to what you're doing
I don't follow. If it connects instantly why would I need a few frames of delay?
if it worked in online mode then that delay might have masked another issue
I see
Exception: This view doesn't have a model yet. Wait until the model is present before interacting with the ownership.
suggests that shouldn't be the case though right?
Unless the room connects in awake, and my scripts wait for connection in awake, and so it could be an execution order issue? But offline mode is set when we connect so I'm not sure if that makes since either.
Just brainstorming. It's hard to diagnose where I should start first.try onmodelreplaced instead of waiting in awake
Scene RealtimeViews only register with their Realtime in Start(). It's inside this registration process that they're assigned a model.
There's 2 ways to approach this:
1. You could try using OnModelReplaced to access your models as Mechabit mentioned. These will be called in Start() when the views register.
2. Or you could connect/launch the offline mode after the 1st frame (or at least after or at the end of the 1st Start), by which point all views have registered. Although you still won't be able to access models inside components' Awake(). So 1 is probably the safest bet here.
I do agree it's unintuitive, perhaps Realtime.Connect on offline mode should defer until after Start()
I'll look into improving this but for now you should try those workarounds
Thanks the both of you! Looking into these fixes today.
Alright so I'm going through my code and it looks like I never actually access the model in
Awake
. I do, on the other hand, subscribe to didConnectToRoom
in Awake
and then access the model in didConnectToRoom
. So, I cleaned that up (assuming didConnectToRoom
will be called before the model is registered) and I am still getting errors.
Looking more closely at the error, I'm confused by all the mentions of UI. I suspect something else is going on here?
Like DrawOwnershipSettings
? Is this an issue with the inspector GUI for RealtimeViews?Yeah it's starting to sound like a bug on our side. I'll test a scene in offline mode to see if I get the same UI error
It's noteworthy to mention again that the errors happen most of the time, but not all of the time.
Though whatever is happening is not benign
@NormalMark you haven't happened to have a chance to look a test scene yet have you?
If it saves you some time I can take a crack at a test project
That being said offline mode is not an immediately crucial feature for this project
I haven't looked yet. That would help me a lot actually 🙂
For sure I'll boot up a new project now
Okay sooo
I did have my
realtime.Connect
in Awake
And that seems to have maybe been the issue (I should connect in Start
?)
Still testing... If true though I'm embaressed I didn't pick up on that earlier.
This does seem to be the case. Offline mode seems to be working flawlessly now.
Moral of the story: Room connection needs to happen in Start
not Awake
. I should have picked up this might have been the issue when it was pointed out that the model should not be accessed in Awake
.
Anyway, the time Normcore and its community puts into its users is really appreciated.Glad it's sorted for now! I might add this to the docs or address this issue somehow. Because it's not unreasonable to want to call connect in
Awake
.
Even Start
might be too early because scene realtime views register themselves in Start
. Depending on the execution order you might get lucky or unlucky 😓you can add a 1 frame delay to offline mode connect to mimic the behaviour of a normal connect
that would be the lazy way which I am very much lol
That is a good idea 🙂 I'll give it a shot
This would be useful!
So you would recommend Mechabit's frame delay approach?
Yeah, I'm thinking of making that the built-in behavior somehow. I put it on my todo list.
Cool!