[Из песочницы] Occlusion Culling и LOD для Unity Indie
Доброго времени суток! В качестве хобби ковыряю движок Unity. Хобби явно некоммерческое, поэтому особой нужды в Pro-версии не испытываю. Pro, конечно же, посурьезнее Indie, но для разработки, например, под Android/iOS возможностей второй вполне хватает. За исключением одной — оптимизации и связанного инструментария.Раскидистая клюква, созданная силами движка имеет полторы — две тысячи треугольников. Высокополигональный замок/машинка заставляют картинку в среднем телефоне шизофренически подергиваться, а красивый шейдер для воды — надолго застыть в позе роденовского мыслителя. Ясно, что при появлении в кадре пары — тройки таких объектов, все будет жутко глючить и тормозить.
В Pro есть крайне нужная штука, называется Occlusion Culling. Кратко — отрисовываются только объекты, попадающие в поле зрения камеры (скриншоты под катом). Посмотрел опять на стоимость Pro, почесал затылок, обиделся и ушел сначала искать, а потом и писать костыли.Без OcclusionCulling:
С OcclusionCulling:
Неплохой пример того, что умные люди уже придумали: Simple LOD Manager. Суть в том, что при приближении к объектам низкополигональная модель (куб) заменяется высокополигональной (например, детализированное здание). Конечно, использовать цикл в Update () не есть хорошо, но идея достойна уважения.
Моим нуждам вполне удовлетворяет небольшая дальность прорисовки, низкополигональные модели мне не нужны. Из тяжелых объектов — только нативные деревья, поэтому идею я немного подсократил. Почему бы не отрисовывать тяжелый объект при приближении к нему игрока?
На выходе имеем скрипт, который вешается на нужный объект и имеет всего один параметр — Distance. Код простой, можно использовать в тестовых сценах.
public var distance = 100f; private var meshRnd: MeshRenderer; private var _collider: BoxCollider; function Awake () { meshRnd = gameObject.GetComponentInParent (MeshRenderer);
_collider = gameObject.AddComponent (BoxCollider); _collider.isTrigger = true; _collider.size = Vector3(distance, distance, distance); } function OnTriggerEnter (player: Collider) { if (player.tag==«Player») meshRnd.enabled = true; }
function OnTriggerExit (player: Collider) { if (player.tag==«Player») meshRnd.enabled = false; } Ловим компонент MeshRenderer объекта, который отвечает за прорисовку самой модели. Создаем коллайдер — в этом случае box, c ребром distance — и делаем его триггером. Если кто — то с тэгом Player вламывается в коллайдер, он срабатывает и отрисовывает модель.Дистанцию удобнее всего подбирать в режиме Window > Layouts > 2 by 3.
Перед запуском деактивируйте MeshRenderer объекта, на который вешается скрипт.
Удачи.