Как инстанциировать ассет асинхронно? - Форум Игроделов
Пн, 10 Фев 2025, 11:24 
 
Приветствую Вас Гость Главная | Регистрация | Вход
Новые сообщения · Участники · Правила форума · Поиск · RSS ]
  • Страница 1 из 1
  • 1
Как инстанциировать ассет асинхронно?
JohnsonДата: Сб, 08 Июн 2013, 20:42 | Сообщение # 1
 
Сообщений: 24
Награды: 0
Репутация: 0
Статус: Offline
Здравствуйте, уважаемые.

При инстанциации большой сцены возникает подвисание. Как его избежать?
Ассет загружаю как обычно:

Код
    public IEnumerator InstantiateAsset(string assetName, OnProgress onProgress, OnLoaded onLoaded) {
         WWW asset = WWW.LoadFromCacheOrDownload("file://" + Application.dataPath + "/AssetBundles/" + assetName + ".unity3d", 2);
         while (!asset.isDone) {
             if (onProgress != null)
                 onProgress(asset.progress);
             yield return null;
         }
         if (onProgress != null)
             onProgress(1f);
         yield return asset;
         AssetBundle assetBundle = asset.assetBundle;
         asset.Dispose();
         Object go = Object.Instantiate(assetBundle.mainAsset, new Vector3(0, 0, 0), new Quaternion(0, 0, 0, 0));
         go.name = assetName;
         assetBundle.Unload(true);
         if (onLoaded != null)
             onLoaded();
     }


Не хочется игровой мир делить на слишком мелкие куски, чтобы не было подтормаживания при ходьбе...
 
СообщениеЗдравствуйте, уважаемые.

При инстанциации большой сцены возникает подвисание. Как его избежать?
Ассет загружаю как обычно:

Код
    public IEnumerator InstantiateAsset(string assetName, OnProgress onProgress, OnLoaded onLoaded) {
         WWW asset = WWW.LoadFromCacheOrDownload("file://" + Application.dataPath + "/AssetBundles/" + assetName + ".unity3d", 2);
         while (!asset.isDone) {
             if (onProgress != null)
                 onProgress(asset.progress);
             yield return null;
         }
         if (onProgress != null)
             onProgress(1f);
         yield return asset;
         AssetBundle assetBundle = asset.assetBundle;
         asset.Dispose();
         Object go = Object.Instantiate(assetBundle.mainAsset, new Vector3(0, 0, 0), new Quaternion(0, 0, 0, 0));
         go.name = assetName;
         assetBundle.Unload(true);
         if (onLoaded != null)
             onLoaded();
     }


Не хочется игровой мир делить на слишком мелкие куски, чтобы не было подтормаживания при ходьбе...

Автор - Johnson
Дата добавления - 08 Июн 2013 в 20:42
HunjethДата: Вс, 09 Июн 2013, 16:28 | Сообщение # 2
 
Сообщений: 354
Награды: 1
Репутация: 112
Статус: Offline
ну так сцена большя, никак

побгдужать мир кусками :
быстродействие
малое потребление памяти
быстро

побгдужать мир целиком :
зависания
использует много памяти
долго ждать

можно :
использовать LOD
или окно згрузки как в ксс например


Сообщение отредактировал Hunjeth - Вс, 09 Июн 2013, 16:38
 
Сообщениену так сцена большя, никак

побгдужать мир кусками :
быстродействие
малое потребление памяти
быстро

побгдужать мир целиком :
зависания
использует много памяти
долго ждать

можно :
использовать LOD
или окно згрузки как в ксс например

Автор - Hunjeth
Дата добавления - 09 Июн 2013 в 16:28
JohnsonДата: Вс, 09 Июн 2013, 16:44 | Сообщение # 3
 
Сообщений: 24
Награды: 0
Репутация: 0
Статус: Offline
Про LOD (а точнее про Culling Occlusion) я думал уже... Но сомневаюсь.

Мир планирую огромный (более 1000 кв. км.), поэтому вариант с полным миром не рассматривал изначально. Одни только терраины забьют память подчистую.
Сейчас мир нарезан на чанки 1024*1024, при загрузке такого чанка клиент подвисает на секунду где-то...
Если "неудачно" подошел в место, из которого загружается сразу 3 чанка - то вообще ад.
Неприятно будет, если при путешествии по миру игроки будут постоянно подвисать.

Локационный мир тоже не рассматриваю - игра онлайновая. В качестве локаций планирую только инстансы.

PS: нарезать на ещё более мелкие чанки, думаю, абсурдно... Замучаемся сводить их.


Сообщение отредактировал Johnson - Вс, 09 Июн 2013, 16:50
 
СообщениеПро LOD (а точнее про Culling Occlusion) я думал уже... Но сомневаюсь.

Мир планирую огромный (более 1000 кв. км.), поэтому вариант с полным миром не рассматривал изначально. Одни только терраины забьют память подчистую.
Сейчас мир нарезан на чанки 1024*1024, при загрузке такого чанка клиент подвисает на секунду где-то...
Если "неудачно" подошел в место, из которого загружается сразу 3 чанка - то вообще ад.
Неприятно будет, если при путешествии по миру игроки будут постоянно подвисать.

Локационный мир тоже не рассматриваю - игра онлайновая. В качестве локаций планирую только инстансы.

PS: нарезать на ещё более мелкие чанки, думаю, абсурдно... Замучаемся сводить их.

Автор - Johnson
Дата добавления - 09 Июн 2013 в 16:44
HunjethДата: Вс, 09 Июн 2013, 16:50 | Сообщение # 4
 
Сообщений: 354
Награды: 1
Репутация: 112
Статус: Offline
Occlusion Culling это не тоже самое что LOD
для открытого мира лучше использовать LOD ибо у тебя видео карта загнется

LOD : http://en.wikipedia.org/wiki/Level_of_detail

Occlusion Culling : Wiki
Цитата
Ситуация, в которой два объекта расположены приблизительно на одной линии и один объект, расположенный ближе к виртуальной камере или порту просмотра (англ. viewport), частично или полностью закрывает видимость другого объекта. В графическом конвейере (англ. Graphics pipeline) используется «окклюзивное обрезание» (англ. occlusion culling) для удаления скрытых поверхностей прежде, чем к ним начнут применяться растеризация и шейдеры.


Сообщение отредактировал Hunjeth - Вс, 09 Июн 2013, 16:55
 
СообщениеOcclusion Culling это не тоже самое что LOD
для открытого мира лучше использовать LOD ибо у тебя видео карта загнется

LOD : http://en.wikipedia.org/wiki/Level_of_detail

Occlusion Culling : Wiki
Цитата
Ситуация, в которой два объекта расположены приблизительно на одной линии и один объект, расположенный ближе к виртуальной камере или порту просмотра (англ. viewport), частично или полностью закрывает видимость другого объекта. В графическом конвейере (англ. Graphics pipeline) используется «окклюзивное обрезание» (англ. occlusion culling) для удаления скрытых поверхностей прежде, чем к ним начнут применяться растеризация и шейдеры.

Автор - Hunjeth
Дата добавления - 09 Июн 2013 в 16:50
JohnsonДата: Вс, 09 Июн 2013, 17:13 | Сообщение # 5
 
Сообщений: 24
Награды: 0
Репутация: 0
Статус: Offline
Знаю я что такое LOD.
Я тут проводил эксперименты с размещением огромного количества хайполи объектов с лодом и без.
Результаты мало отличаются, поэтому думается мне, что юнька сама полигоны совмещает (эта мысль есть ещё у нескольких человек, находил подобные ответы в сети).

Но, пусть даже лод.
Допустим, мир 100*100 чанков. Памяти не хватит в любом случае, ведь кроме терраинов есть ещё приличное количество объектов на нем.

Есть ещё мысль каждый чанк разбивать на составляющие (например, терраин, деревья, здания, остальное) и грузить их по очереди. Насколько хорошая идея - не знаю, если ни чего лучше не придумаю - буду пробовать так.

Добавлено (09 Июн 2013, 17:13)
---------------------------------------------
Но всё же меня смущает отсутствие возможность инстанциировать объект по частям, асинхронно...
Ведь в памяти в любом случае создается всё дерево объектов. Почему бы разработчикам не сделать возможность из бандла получать все объекты отдельно.
Тогда бы проблем вообще не было - знай себе инстанциируй их в сопрограмме...

 
СообщениеЗнаю я что такое LOD.
Я тут проводил эксперименты с размещением огромного количества хайполи объектов с лодом и без.
Результаты мало отличаются, поэтому думается мне, что юнька сама полигоны совмещает (эта мысль есть ещё у нескольких человек, находил подобные ответы в сети).

Но, пусть даже лод.
Допустим, мир 100*100 чанков. Памяти не хватит в любом случае, ведь кроме терраинов есть ещё приличное количество объектов на нем.

Есть ещё мысль каждый чанк разбивать на составляющие (например, терраин, деревья, здания, остальное) и грузить их по очереди. Насколько хорошая идея - не знаю, если ни чего лучше не придумаю - буду пробовать так.

Добавлено (09 Июн 2013, 17:13)
---------------------------------------------
Но всё же меня смущает отсутствие возможность инстанциировать объект по частям, асинхронно...
Ведь в памяти в любом случае создается всё дерево объектов. Почему бы разработчикам не сделать возможность из бандла получать все объекты отдельно.
Тогда бы проблем вообще не было - знай себе инстанциируй их в сопрограмме...


Автор - Johnson
Дата добавления - 09 Июн 2013 в 17:13
seamanДата: Вс, 09 Июн 2013, 19:38 | Сообщение # 6
Гуру
 
Сообщений: 1748
Награды: 10
Репутация: 660
Статус: Offline
Цитата
Почему бы разработчикам не сделать возможность из бандла получать все объекты отдельно.

Не понял. А почему нельзя? AssetBundle.LoadAsync(имя ассета) - загружает конкретный ассет из бандла и асинхронно.
 
Сообщение
Цитата
Почему бы разработчикам не сделать возможность из бандла получать все объекты отдельно.

Не понял. А почему нельзя? AssetBundle.LoadAsync(имя ассета) - загружает конкретный ассет из бандла и асинхронно.

Автор - seaman
Дата добавления - 09 Июн 2013 в 19:38
JohnsonДата: Вс, 09 Июн 2013, 20:25 | Сообщение # 7
 
Сообщений: 24
Награды: 0
Репутация: 0
Статус: Offline
Дак загружает-то асинхронно, а инстанциировать-то приходится весь объект (долго).

Код
        Object go = Object.Instantiate(assetBundle.mainAsset, new Vector3(0, 0, 0), new Quaternion(0, 0, 0, 0));


Сообщение отредактировал Johnson - Вс, 09 Июн 2013, 20:26
 
СообщениеДак загружает-то асинхронно, а инстанциировать-то приходится весь объект (долго).

Код
        Object go = Object.Instantiate(assetBundle.mainAsset, new Vector3(0, 0, 0), new Quaternion(0, 0, 0, 0));

Автор - Johnson
Дата добавления - 09 Июн 2013 в 20:25
seamanДата: Вс, 09 Июн 2013, 22:25 | Сообщение # 8
Гуру
 
Сообщений: 1748
Награды: 10
Репутация: 660
Статус: Offline
О чем Вы вообще пишете?
Вы спросили (цитата):
Цитата
Почему бы разработчикам не сделать возможность из бандла получать все объекты отдельно.

Я ответил - они это давным давно сделали. Вам никто не мешает в бандл засунуть хоть 100500 объектов и получить их отдельно упомянутой функцией.
Далее. Если Вы инстанцируете сложный объект - это делается, конечно долго. Но Вы же сами предложили выход из ситуации (цитата):
Цитата
знай себе инстанциируй их в сопрограмме...

Вопрос: все уже есть - что то еще надо? Как говорится - разделяй и властвуй!
 
СообщениеО чем Вы вообще пишете?
Вы спросили (цитата):
Цитата
Почему бы разработчикам не сделать возможность из бандла получать все объекты отдельно.

Я ответил - они это давным давно сделали. Вам никто не мешает в бандл засунуть хоть 100500 объектов и получить их отдельно упомянутой функцией.
Далее. Если Вы инстанцируете сложный объект - это делается, конечно долго. Но Вы же сами предложили выход из ситуации (цитата):
Цитата
знай себе инстанциируй их в сопрограмме...

Вопрос: все уже есть - что то еще надо? Как говорится - разделяй и властвуй!

Автор - seaman
Дата добавления - 09 Июн 2013 в 22:25
JohnsonДата: Пн, 10 Июн 2013, 08:37 | Сообщение # 9
 
Сообщений: 24
Награды: 0
Репутация: 0
Статус: Offline
Никак не могу сообразить, что Вы имеете в виду.

Сейчас я инстанциирую так:

Object go = Instantiate(bundle.mainAsset);

Но в корутине же всеравно оно так же будет добавляться в мир, а это займет время. Или я не прав? Можно увидеть Ваш вариант программы?
 
СообщениеНикак не могу сообразить, что Вы имеете в виду.

Сейчас я инстанциирую так:

Object go = Instantiate(bundle.mainAsset);

Но в корутине же всеравно оно так же будет добавляться в мир, а это займет время. Или я не прав? Можно увидеть Ваш вариант программы?

Автор - Johnson
Дата добавления - 10 Июн 2013 в 08:37
seamanДата: Пн, 10 Июн 2013, 10:23 | Сообщение # 10
Гуру
 
Сообщений: 1748
Награды: 10
Репутация: 660
Статус: Offline
В бандле может быть сколько угодно объектов. Разбиваете наиболее сложные на части и истанцируете по частям. Достать один префаб (цельный объект или часть большого) из бандла можно указанной функцией AssetBundle.LoadAsync. Чтобы не было тормозов достаем и инстанцируем не все сразу, а частями, размазывая во времени. Проще всего это сделать корутиной.
Например. mainasset в бандле - это список всех ассетов в бандле ScriptableObject, в котором массив - имена всех ассетов в бандле.
Достаем этот ассет.
Код
string[] names = ((ScriptableObject)assetBundle.mainasset).names;

Используем его для того что бы достать все остальные ассеты.
Код
StartCoroutine(InstantiateBundle(assetBundle, names));

Сама корутина:
Код
IEnumerator InstantiateBundle(AssetBundle assetBundle, string[] names)
{
       foreach(string name in names)
       {
          GameObject go = (GameObject) Instantiate(assetBundle.Load(name));
          yield return null;
       }
}

Тут не использовал асинхронную загрузку. Сам подумай как.
ЗЫ: писал прямо в форуме, мог напортачить где то, так что проверяй. (даже знаю где smile )
 
СообщениеВ бандле может быть сколько угодно объектов. Разбиваете наиболее сложные на части и истанцируете по частям. Достать один префаб (цельный объект или часть большого) из бандла можно указанной функцией AssetBundle.LoadAsync. Чтобы не было тормозов достаем и инстанцируем не все сразу, а частями, размазывая во времени. Проще всего это сделать корутиной.
Например. mainasset в бандле - это список всех ассетов в бандле ScriptableObject, в котором массив - имена всех ассетов в бандле.
Достаем этот ассет.
Код
string[] names = ((ScriptableObject)assetBundle.mainasset).names;

Используем его для того что бы достать все остальные ассеты.
Код
StartCoroutine(InstantiateBundle(assetBundle, names));

Сама корутина:
Код
IEnumerator InstantiateBundle(AssetBundle assetBundle, string[] names)
{
       foreach(string name in names)
       {
          GameObject go = (GameObject) Instantiate(assetBundle.Load(name));
          yield return null;
       }
}

Тут не использовал асинхронную загрузку. Сам подумай как.
ЗЫ: писал прямо в форуме, мог напортачить где то, так что проверяй. (даже знаю где smile )

Автор - seaman
Дата добавления - 10 Июн 2013 в 10:23
JohnsonДата: Пн, 10 Июн 2013, 18:37 | Сообщение # 11
 
Сообщений: 24
Награды: 0
Репутация: 0
Статус: Offline
Спасибо огромнейшее! То, что нужно!

Про напортачить - это мне не страшно, мне нужно было понять сам алгоритм.

Добавлено (10 Июн 2013, 18:37)
---------------------------------------------
Ни как не могу разобраться...

Код
string[] names = ((ScriptableObject)assetBundle.mainasset).names;

Не работает. Нету у ScriptableObject поля names.

Разобрался с функциями LoadAll и LoadAsync, но все равно шняга, они инстанциируют все лоды, и без скриптов.

Помоги, пожалуйста, точнее smile
 
СообщениеСпасибо огромнейшее! То, что нужно!

Про напортачить - это мне не страшно, мне нужно было понять сам алгоритм.

Добавлено (10 Июн 2013, 18:37)
---------------------------------------------
Ни как не могу разобраться...

Код
string[] names = ((ScriptableObject)assetBundle.mainasset).names;

Не работает. Нету у ScriptableObject поля names.

Разобрался с функциями LoadAll и LoadAsync, но все равно шняга, они инстанциируют все лоды, и без скриптов.

Помоги, пожалуйста, точнее smile

Автор - Johnson
Дата добавления - 10 Июн 2013 в 18:37
  • Страница 1 из 1
  • 1
Поиск:
Загрузка...

Game Creating CommUnity © 2009 - 2025