Как стать автором
Обновить

Комментарии 7

Статья супер, есть даже ответ на вопрос который у меня возник в процессе чтения, раз уж используется C# 7+ (ответ в последнем примечании). Только дело не в любви, если мне не изменяет память Coroutines выполняются в Main Thread, в отличие от async/await, для закачки наверно лучше все таки задействовать другие потоки.
Спасибо). Про async/await, тут нужно понимать, что если их использовать в чистом виде, то работать все будет в том же потоке, именно переход с Coroutine на них простой, однако если хочется именно многопоточности, нужно использовать Task.Run и тут возникает сложность с невозможностью доступа к всем наследникам UnityEginge.Object в таких задачах. Вот так приблизительно будет выглядеть основная функция для сетевого запросе через async/await, в данном случае она в основном потоке выполняется
private async Task<UnityWebRequest> WebRequest(CancellationTokenSource cancelationToken, UnityWebRequest request, Action<float> progress)
    {
        while (!Caching.ready)
        {
            if (cancelationToken.IsCancellationRequested)
            {                             
                return null;
            }

            await new WaitForUpdate();
        }

#pragma warning disable CS4014
        request.SendWebRequest();
#pragma warning restore CS4014

        while (!request.isDone)
        {
            if (cancelationToken.IsCancellationRequested)
            {                
                request.Abort();
                request.Dispose();

                return null;                
            }
            else
            {
                progress?.Invoke(request.downloadProgress);

                await new WaitForUpdate();
            }
        }

        progress?.Invoke(1f);
           
        return request;        
    }

В AssetBundleWrapper.LoadAsset условие должно быть инвертировано, судя по логике метода:

if (string.IsNullOrEmpty(assetPath))
{
    return AssetDatabase.LoadAssetAtPath<T>(assetPath);
} else
{
    return default;
}
да спасибо, исправил в статье
Пробовал скачивать аудио клип с помощью
DownloadHandlerAudioClip.GetContent(request)
и упаковав его в AssetBundle:

AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(www);
var audioClip = bundle.LoadAssetAsync<AudioClip>(bundle.GetAllAssetNames()[0]);

Но в обоих случаях происходит заметное зависание приложения при попытке получить AudioClip, хоть во втором варианте и Async вызов.
Также нельзя сделать это в отдельном треде, т.к. GetContent это вызов Unity API.

Есть ли способы получить контент без заметных фризов?
var audioClip = bundle.LoadAssetAsync(bundle.GetAllAssetNames()[0]); Не очень понятная строчка, поскольку в таком виде вы получите не audioClip, а AssetBundleRequest, который явялется асинхронной операцией и в этом случае получить из него данно можно через yield return, соотвественно через запуск Coroutine.
Выше в статье есть пример кода:
public void LoadAssetAsync<T>(string name, Action<T> result) where T : UnityEngine.Object
    {
        var request = _assetBundle.LoadAssetAsync<T>(name);

        TaskManager.Task.Create(request)
                        .Subscribe(() =>
                        {
                            result(request.asset as T);

                            Unload(false);
                        })
                        .Start();
    }
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории