[Из песочницы] Occlusion Culling и LOD для Unity Indie

Доброго времени суток! В качестве хобби ковыряю движок Unity. Хобби явно некоммерческое, поэтому особой нужды в Pro-версии не испытываю. Pro, конечно же, посурьезнее Indie, но для разработки, например, под Android/iOS возможностей второй вполне хватает. За исключением одной — оптимизации и связанного инструментария.Раскидистая клюква, созданная силами движка имеет полторы — две тысячи треугольников. Высокополигональный замок/машинка заставляют картинку в среднем телефоне шизофренически подергиваться, а красивый шейдер для воды — надолго застыть в позе роденовского мыслителя. Ясно, что при появлении в кадре пары — тройки таких объектов, все будет жутко глючить и тормозить.

В Pro есть крайне нужная штука, называется Occlusion Culling. Кратко — отрисовываются только объекты, попадающие в поле зрения камеры (скриншоты под катом). Посмотрел опять на стоимость Pro, почесал затылок, обиделся и ушел сначала искать, а потом и писать костыли.Без OcclusionCulling:

image

С OcclusionCulling:

image

Неплохой пример того, что умные люди уже придумали: 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 объекта, на который вешается скрипт.

Удачи.

© Habrahabr.ru