Unity: Realm stalls when using Enter Play Mode Options active (depends on Domain Reload)

Hello! Just came here from the stream that Luce and @nraboy hosted, classic Unity experience (I teach Unity to first-timers a lot, so I always squirm when I see even seasoned software pros get stuck :))

But here’s my question / issue:

Debug.Log($"Awaiting connection to Realm App <color=green>censored</color>:");
_app = Realms.Sync.App.Create(RealmAppID);
_user = await _app.LogInAsync(Credentials.EmailPassword("test@mail.domain", "password"));

I have some code like this and it works great with Realm / Realm Sync. But it only works once, so I hit play, it works, then it fails. Once I have any code changes that trigger a recompile, it works.

Quick repro video of what this feels like:

It hangs on the await in the last statement of the code snippet above.

This is caused by Unity not reloading the .NET Domain, which is an advanced option that can be disabled in Project Settings->Editor->Enter Play Mode Settings. Recompiles always trigger domain reloads, which is why that alleviates the problem temporarily. This setting is used a lot by devs around the world because it seriously speeds up iteration time as projects grow - normally, Unity reloads the Domain whenever the Play button is pressed, but that quickly takes 1, 2, or more seconds (especially in DOTS projects or mature production code bases). It does come with some caveats that require slightly cleaner coding practices.

Usually, this sort of “run-once” behaviour is an indicator that some resources that live in a static context aren’t properly unloaded or closed. A acceptable fix would be to expose some functions that manually control the lifecycle of Realm’s runtime that does “nothing” on first run but will re-initialize all static fields and singletons with null, so they will be properly recreated as needed.

Background / Protip / How to shoot yourself in the foot:

If you’ve ever been annoyed by the “Reloading Script Assemblies” progress popup, I have a treat for you and that’s :rainbow: Skipping :rainbow: the :rainbow: Domain :rainbow: Reload :rainbow:

This shows the difference in iteration times (first the default out of the box behaviour, then with Enter Play Mode Options enabled), already very pronounced on a very small project (~70 lines of code). I had DOTS prototypes that had domain reloads of 30+ seconds, but also a medium size mobile game will quickly rack up 5+ seconds of “Reloading Script Assemblies” time.

@nirinchev, do you have any experience with Domain Reloads?

cc @Luce_Carter

1 Like

Thanks for the quick reply and signal boost. :slight_smile: Also thanks for loopin Luce in, I couldn’t find the right handle.

Linking some supplemental documentation here:

Hey folks - to be honest, I don’t have a whole lot of large project experience with Unity and didn’t know about that setting. I’ll need to test it out and understand what we’re doing wrong there.


No problem, if I wanted to give it a concise issue summary:

App.LogInAsync(…) only works once per Domain Reload in multiple Unity Play Mode sessions

My lowkey suspicion is it may be NativeCommon.Initialize() and that it perhaps needs some of the goodness from the Domain Reloading article in the Unity Manual applied to it (or its friends). The attribute in question can be used in arbitrary classes, doesn’t have to be a UnityEngine.Object decendant.

(kind of interesting that other .NET devs haven’t encountered this issue, Unity is an outlier with its frequent Domain Reloads by default; a behaviour they are actively working to get rid of btw., and that’s keeping them from going to .NET 6.0)

Yeah, domain reloading has been a bit of a pain to deal with when adding Unity support and it’s clear we didn’t handle all corner cases. Your detailed report and pointers will help a great deal here and I hope the fix won’t be too involved. I filed a Github issue that you can subscribe for updates. In interest of transparency though, we’re having an engineering offsite next week and the schedule is packed with discussions, so I don’t think we’ll be able to get to it until after that.