Bumping to provide more information. The issue occurs when the background loading thread is executing something while one of the following two methods are called in the main thread (there may be more than these 2, but these are what I have identified so far).
- AssetBundle.LoadAssetBundle.
This method is triggered by Unity automatically a few frames after calling Addressables.LoadAssetAsync. I think it is triggered when the asset bundle that contains the asset you want to load is loaded. Unity reads the file and queues up the actual async loading of the asset via the background loading thread. However, if the background thread is currently loading some other asset or it’s dependencies, there is a chance that LockPersistentManager will stall out the main thread for a bit (it doesn’t always stall out).
My guess is Unity stalls because there’s some sort of overlap between the dependencies of the asset currently being loaded in the background, and the new asset which LoadAssetBundle was called for. I would love some confirmation of this by a Unity dev though!
- Application.Integrate Assets in Background.
Again, this will stall out if it’s triggered while the background loading thread is running. Again, it doesn’t always stall out, so I guess it must only stall out when there are dependency overlaps.
Is there anyone out there that has experience with this subject? All other threads I can find that mention LockPersistentManager seem to come down to some specific asset types taking a while to load (textures, audio, etc.) or some issue with activating the game objects (which is not the case here).
I would really just love some feedback on how to organize the Addressable Assets or perform the async loading calls in order to avoid LockPersistentManager as much as possible.
Thanks!
Edit: I spoke to my good friend Chat GPT and I think I have a better grasp of what’s going on.
Basically, Persistent Manager “manages resources and assets that need to remain loaded and persist across the lifecycle of the application.”
LockPersistentManager is an attempt to lock this manager, to allow one thread to do some work while avoiding race conditions with other threads.
When you see LockPersistentManager in a thread, that means the thread is waiting for another thread to finish some work. So you need to look in that other thread to see what is stalling everything! This makes sense and I feel like an idiot for not understanding this sooner. Oh well.
However, I still have a few questions. Unity is using the synchronous AssetBundle.LoadAssetBundle to load the Asset Bundle. I believe there are async versions of this method available; why doesn’t Unity use them, or some other async method that doesn’t cause the main thread to be blocked?
When loading addressable prefabs, there is no way to delay main thread integration. However, let’s say I switched to using addressable scenes, which can be activated manually. Is there some way to detect when the Persistent Manager is locked in order to delay the activation of the scene until the next frame?