Dror
Dror

Reputation: 2588

Optimal way for managing async loading of assets on game load

I'm developing a mobile idle game for iOS and Android and I'm now at the stage where I'm building the game's save/load infrastructure.

When opening the game app for loading a previously saved session, after the app has been closed, and before the loading the previously saved session, I'm loading mandatory game assets, mostly ScriptableObjects, with Addressables asynchronously like this:

StartCoroutine(LoadInventoryAssets());
StartCoroutine(LoadCharacterAssets());
StartCoroutine(LoadSoundAssets());

Each LoadAssets function looks roughly like this:

_assetsLoadingOp = Addressables.LoadAssetsAsync<AssetType>("AssetLabel", null);
yield return _assetsLoadingOp;

if (_assetsLoadingOp.IsDone) 
{
     _results = _assetsLoadingOp.Result
}

Finally, when all of these are loaded I run the function that loads the relevant scene, game objects, and injects the saved data. This function must only run after all the previous Addressable assets were loaded.

yield return StartCoroutine(LoadSavedGame());

The problem with the above is that the LoadSavedGame function might run before all of the previous asset loading functions were completed.

I could solve that by adding yield return to all Coroutines, but wouldn't that make each of them load sequentially instead of in parallel?

Any thoughts on what's the best approach for this would be greatly appreciated.

Upvotes: 0

Views: 641

Answers (2)

Dror
Dror

Reputation: 2588

OK so eventually I went with this approach:

bool? inventoryAssetsLoadedResult = null, characterAssetsLoadedResult = null, soundAssetsLoadedResult = null; 

StartCoroutine(LoadInventoryAssets((result)=> inventoryAssetsLoadedResult = result));
StartCoroutine(LoadCharacterAssets((result)=> characterAssetsLoadedResult = result));
StartCoroutine(LoadSoundAssets((result)=> soundAssetsLoadedResult = result));

yield return new WaitUntil(() => inventoryAssetsLoadedResult.HasValue & characterAssetsLoadedResult.HasValue & soundAssetsLoadedResult.HasValue);

Each coroutine looks similar to this:

public IEnumerator LoadInventoryAssets(Action<bool> callback)
        {
            yield return new WaitUntil(() => _inventoryLoadingOp.IsDone);
            callback(true);
        }

Any suggestions for improvements are welcome.

Upvotes: 0

shingo
shingo

Reputation: 27342

You can just use an integer to count how many functions have been complete. In the end of each LoadAssets function:

if(++task == 3)
    StartCoroutine(LoadSavedGame());

Upvotes: 0

Related Questions