0
\$\begingroup\$

So from the official documentation and unity forum now I know that there's async version of LoadFromFile (that I also will probably call UnityWebRequest.GetAssetBundle later for updated asset). Now the problem is where can I call it, and how to get the .progress value, converting from this:

public AssetManager()
{
    if (!useAssetBundle) return;
    foreach (var bundle_name in bundle_names)
    {
        var full_path = Path.Combine(Application.streamingAssetsPath + "/Bundle/", bundle_name);
        var bundle = AssetBundle.LoadFromFile(full_path);
        if (bundle == null) LogHelper.Critical("Failed to load AssetBundle {0}", full_path);
        bundles[bundle_name] = bundle;
    }
}

To this (that obviously wrong):

private List<AssetBundleCreateRequest> loadPro = new List<AssetBundleCreateRequest>();

private IEnumerator<AssetBundle> _loadOneAssetBundle(string full_path)
{
    var creq = AssetBundle.LoadFromFileAsync(full_path);
    loadPro.Add(creq);
    yield return creq.assetBundle;
}

public AssetManager(MonoBehaviour parent)
{
    if (!useAssetBundle) return;
    foreach (var bundle_name in bundle_names)
    {
        var full_path = Path.Combine(Application.streamingAssetsPath + "/Bundle/", bundle_name);
        var bundle = parent.StartCoroutine(_loadOneAssetBundle(full_path)).assetBundle; // NOPE T_T)
        if (bundle == null) LogHelper.Critical("Failed to load AssetBundle {0}", full_path);
        bundles[bundle_name] = bundle; // NOPE 'n')
    }
}

public void Update()
{
    var progress = 0f;
    foreach (var pro in loadPro)
    {
        progress += pro.progress;
    }
    LogHelper.Debug("Progress %f",progress);
}
\$\endgroup\$
2
\$\begingroup\$

Remember, when you start a coroutine, your execution doesn't block and wait for it to finish. It continues to the next line immediately.

So, the problems in your code are:

var bundle = parent.StartCoroutine(_loadOneAssetBundle(full_path)).assetBundle;

A) StartCoroutine just starts a Coroutine - it doesn't load your asset bundle for you (it doesn't know what an AssetBundle is!) so you can't fetch a reference to your bundle out of it like this.

if (bundle == null) LogHelper.Critical("Failed to load AssetBundle {0}", full_path);
bundles[bundle_name] = bundle;

B) Even if you could, the Coroutine has only just started at this point. The load hasn't had a chance to complete yet, so you're trying to grab your bundle too early.

Instead, you want to read your AssetBundle after the load has finished inside your Coroutine. This adapted straight from the documentation for LoadFromFileAsync:

IEnumerator LoadAssetBundleFromPath(string path)
{
    var bundleLoadRequest = AssetBundle.LoadFromFileAsync(path);

    // Track progress while it's loading.
    loadProgress.Add(bundleLoadRequest);

    // Wait until the load has finished.
    yield return bundleLoadRequest;

    // Done tracking.
    loadProgress.Remove(bundleLoadRequest);

    // NOW it's safe to grab the bundle, since we waited for it to load.
    var myLoadedAssetBundle = bundleLoadRequest.assetBundle;
    if (myLoadedAssetBundle == null)
    {
        Debug.Log("Failed to load AssetBundle!");
        yield break;
    }

    // Put your code that stores / uses the AssetBundle here.
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.