#unity3d #разработка_игр
В 2d платформере очень длинные сцены. Нужно как-то оптимизировать загрузку оных. Но есть нюансы. Можно бы было разбить сцену на чанки и грузить асинхронно, когда приближаешься к чанку. Но проблема в том, что элементы на всей сцене должны обновляться постоянно. Например, npc в конце карты выполняют какие-то действия и могут прокачиваться пока ты к ним добираешься. При использовании порталов герой может переместиться в область совсем далёкую от текущей (где могут быть объекты совсем другого типа, что повлиет на производительность в момент подгрузки). Как быть с нав мешами между чанками?
Ответы
Ответ 1
Если описанные вами проблемы являются очень критичными, то скорее всего, подавляющее большинство оптимизаций, которое может предложить Unity будут являться условно-полезными и будут лечить скорее часть симптомов, нежели проблему в целом. В такой ситуации единственным корректным решением будет разобраться в проблемой сильной связанности кода, то есть заняться правкой архитектуры проекта. Вывод о сильной связанности вытекает из описанных вами пунктов - если логика действий NPC и поиска пути были бы не зашиты в Unity (скорее всего на MonoBehaviour объекты), то все это можно было бы просчитывать в фоне, не заботясь о визуальном представлении. Основной аксиомой к подобному решению является утверждение о том, что большая часть подсистем в юнити (типа навигации, физики и прочего) реализовано не правильно в соответствии с принципами ООП и подходит больше для прототипирования или небольших проектов, где не делается большой упор на оптимальность решения. Если вы хотите использовать Unity для более или менее серьезных вещей, то подобные подсистемы более выгодно реализовать самому, чтобы получить больший контроль. Почему, я утверждаю, что физика или навигация реализованы некорректно? Ответ заключается в том, что с одной стороны, по-другому их реализовать в общем случае у них и не получилось бы, а с другой стороны, все это неразрывно завязано на GameObject'ы, то есть на визуальное представление. Этот факт идет в прямом конфликт с принципом S из семейства SOLID, а также паттерном MVC. Если отступить от всестороннего доверия Unity и написать частные реализации физики и поиска пути (а для 2D платформера это не является сложной задачей) у вас будет возможность получить игру, где все действия можно просчитывать в контроллерах сущностей (из MVC), и обновлять визуальное представление только если оно существует в данный момент. При этом сам мир игры будет жить и совершать действия. Такой подход даст вам возможность при загрузке сцены создавать для всех объектов только Model и Controller, а визуальное представление добавлять только для объектов, которые необходимо отображать в текущий момент (видимые на экране объекты с небольшим запасом по сторонам). Если при этом карта состоит из примерно однородных тайлов, то для визуальных отображений тайлов очень удобно можно будет использовать пул объектов, чтобы ограничиться малым количеством GameObject на сцене. По большей части именно в загрузке/удалении/создании GameObject и заключается бутылочное горлышко производительности Unity3D. Этот факт легко проверяется - достаточно, например, сравнить скорость запуска приложения, где в одном случае на сцене будут загружаться 10 000 GameObject, а в другом - 10 000 не-MonoBehaviour классов. Думаю, о результатах подобного эксперимента легко догадаться - C# классы загрузятся в разы быстрее. Полное кастомное разделение представления и логики даст возможность не делить карту на части, иметь возможность считать поведение любого объекта на сцене и отображать лишь указанную вами часть мира. Если такое решение окажется недостаточно эффективным, в таком случае уже будет смысл применять встроенные в юнити оптимизации, типа LOD, запекания/батчинга и тп.Ответ 2
Скажу сразу, я такого не делал и разсуждаю сугубо теоретически чисто на ассоциациях. К моему ответу не факт что можно относится серьезно т.к. все написанное ниже это сугубая теоретика которая никак не подпитывается практическим опытом. Но авось всплывет что-то полезное. Вариант 1: Есть такая штука как LOD. Уверен, ты знаком с ней. Она относится к графике. И это можно увидеть, например, приближая или отдаляя камеру от terrain. Идея в том, что бы упрощать геометрию обьекта если камера отдаляется. Чем дальше камера -- тем более сильно упрощается геометрия обьекта -- что бы этот обьект минимум ресурсов жрал. Можно пойти по подобному пути в твоей задаче. Не обязательно подгружать и промалевывать все на протяжении всего долгого уровня/мира. Возможно есть смысл иметь переключатель который будет убирать прорисовку/отображение всего что находится достаточно далеко от камеры -- всего что находится в других чанках. В таком случае ты разгрузишь уровень от ненужных предметов и ненужных трат ресурсов. А включать отображение только по триггеру перехода в даную область. Вариант 2: Есть такакая штука как texture baking (запекание теней, освещения и отзеркаливания света на текстурах). Идея в том, что все это просчитываются наперед и дальше ты используешь текстуры с этими тенями в своей игре. Это освобождает железо юзера от просчетов во время игрового процесса, но занимает много "лишней" памяти на винчестере. Эти все просчеты делаются на момент девелопмента игры. Можно пойти по подобному пути в твоей задаче. Не обязательно просчитывать мир в реалтайме. Ты можешь сделать 2-5-10 симуляций твоего мира делая "снепшоты" всего мира каждые 1-5 минут. Когда юзер будет начинать новую игру, он будет рандомно выбирать на одну из этих симуляций. За счет этого можно будет просчитывать в реалтайме только тот чанк в котором сейчас находится юзер, но при этом остальную информацию брать со "снепшота" который будет зависеть от времени игры.
Комментариев нет:
Отправить комментарий