Handling offline to online transition

One thing I’ve been puzzling over with Normcore lately is fallout from needing to wait until connected to a room to spawn in things that need to be synchronized.

For example, you might have an XR game with a player avatar and some objects in that player’s hands (which are driven by physics). These have to exist before you connect to the room, as you navigate the UI, or go to offline areas of the game. But when you connect to a room, things like the players head/hands along with those objects suddenly need to be replicated. What are people’s solutions to this problem?

You could create a variant of your player prefab with Realtime components on it, and sorta delete the old one and spawn in a new one… but that will lead to glitches that are hard to paper over.
You could also spawn in “shadow objects” for the head/heads and other objects, and copy to/from them depending on whether you are local or remote. But then you can’t put things like RealtimeTransform on the actual objects with rigid bodies (because they existed before you connected), so you lose a bit of the magic they perform.

Maybe there is a way I haven’t seen, but it seems like it would be nice to be able to have a prefab in the scene with dormant Realtime components on them. And at the time you connect to a room, you can just say “hey, replicate this now!”.

Are there other approaches people are using to handle this transition from offline to online? thanks!!!

The typical approach I’ve seen is to create an offline prefab / avatar. In our titles you can’t really play the game if you don’t have internet, so we treat our offline prefab as a minimal prefab that only has the necessary components to click the “Reconnect” button on our error dialog.

For games that spend more time in an offline mode, titles typically use the same pattern, but they use a prefab variant for the offline prefab where you take your online prefab, create a variant, and strip the RealtimeView/RealtimeComponents via an overlay. That way anything you add to your online prefab is automatically included in the offline one. You’re right that you’ll need to ensure your scripts can function correctly if those components are missing, but this kind of logic is something you’d need to implement regardless of your approach to offline/online architecture.

Max

Ah cool, so most people are using the first approach I mentioned of having an offline and online player prefab (with one being a variant of the other), and doing a handoff between them when you go online.

The tricky part is to do that handoff seamlessly if your offline prefab is complex. Like say you are holding a sword, when you go online, you’d need to sync state from the offline prefab to the online version so that the sword continues to move seamlessly when it’s swapped. And that state is exactly the sort of state we’d be syncing via normcore…

You also have to pay for a potential glitch if your online prefab has to do some heavy initialization when it’s spawned. If it could be spawned at the start, you can hide that glitch before you fade in from the initial load.

One humble suggestion: maybe some day, we could do a Realtime.Instantiate right at the start (and before connected to a room). Then we can go about our business offline (mostly ignoring the dormant realtime components). BUT when we connect to the room, the initial state for the models can just be pulled directly from state the game was already generating. So instead of swapping from one prefab to the other, we can use a single prefab throughout… Does this make sense or am I dreaming?!

1 Like

It’s definitely a good idea and one I’ve tried to implement previously. The main blocker is how to merge state. If you’ve got state in the room while you’re in offline mode that conflicts with state in the room when you join (let’s say you picked up the sword offline, but online someone else is already holding it) there’s no automatic way to merge the two sets of state.

I hope to implement this API someday, but it’s going to require a large rewrite of Normcore to enable developers to write their own merge conflict resolution logic.

Max

Ahh, I hadn’t considered what happens for projects that use persistence between sessions, so merging would become a thing. I can see how that would be a pretty complicated thing to support for projects that rely on persistence.
For the rest of us, I was imagining a new flag to the options on Realtime.Instantiate like “allowOfflineInstantiate”. Ha, maybe if you also pass “destroyWhenOwnerOrLastClientLeaves” as false, it would just fail until the big rewrite :slight_smile: I can dream can’t I?! Glad to hear this is on your radar either way, and thanks for the responses