Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / Unity - памятка новичкам

Unity - памятка новичкам

Страницы: 1 2 Следующая »
TokarnПостоялецwww9 мар. 20171:10#0
В этом посту я не буду описывать преимущества или недостатки Unity, по сравнению с другими игровыми движками, включая и самописные, так же я надеюсь, что и премногоуважаемые "знатоки" этим тоже не будут заниматься.
Я хочу поделиться своими скромными знаниями и разжевать некоторые совсем уж базовые нюансы работы с движком Unity3D, это в основном те грабли, на которые любят наступать начинающие разработчики.
Информация предназначена для совсем новичков, как в работе с движком, так и в интернет-серфинге и прочим что могло бы помочь в работе с движком.

Во первых - вы легко можете найти всю необходимую информацию непосредственно на сайте юнити.
В многочисленных видео, составленных самими разработчиками движка, выполненных в виде обучающих уроков: https://unity3d.com/ru/learn/tutorials
В подробной документации-руководству к движку: https://docs.unity3d.com/ru/current/Manual/index.html
А так же в документации API скиптов: https://docs.unity3d.com/ru/current/ScriptReference/index.html

Для тех, кто не очень ладит с английским есть:
Способ подключить грубо переведенные автоматическим переводчиком субтитры к видео урокам - в плеере нажмите "настройки" (шестеренка) -> нажмите "субтитры" -> английский -> снова "субтитры" -> перевести -> выберите русский язык.

Способ подключить удобный автоматический переводчик к браузеру, что даст возможность перевести либо отдельные фразы, либо всю страницу полностью, без нужды перехода на страницу онлайн переводчика.
Есть масса способов это сделать к каждому браузеру, как вариант можно использовать связку Google Chrome + расширение Google Translate - в браузере в правом верхнем углу нажмите на три вертикальные точки, войдите в "настройки" -> расширения -> еще расширения -> ввести в поиске "переводчик" -> выбрать Google Translate.
Использовать его просто - выделяете строчку, которую нужно перевести и в зависимости от её длинны вы либо щелкаете на появившуюся иконку переводчика, либо щелкаете правой кнопкой мыши и переходите на страницу переводчика, выбрав "Google переводчик"
Так же есть возможность перевести всю страницу - переводчик либо спросит об этом сам, либо в правом верхнем углу браузера нажмите на иконку переводчика и выберите "перевести страницу" (но со страницами с iFrame вложениями это не работает, допустим вы не переведете страницу с документацией API скриптов Unity этим способом)

Во вторых - если вам либо лень погружаться в рутину изучения документации, либо вы уже знаете азы и даже работаете над какими то проектами, могу объяснить некоторые прописные истины работы с движком:
1. Физика 3D
Во первых, если вы хотите использовать физику в своих проектах, то не используйте при перемещении и вращении физических объектов обращение к transform объекта, используйте вместо этого обращение к rigidbody, это даст физическом движку правильную информацию о движении объекта, оно будет сглаженным и в случае столкновения объект правильно среагирует на него. Обращение же к transform, по сути просто "телепортирует" объект без использовании физики, даже если это выглядит гладко, его движение состоит из тысяч "телепортаций", вместо настоящего движения.

1) Статические объекты - это объекты, которые определяют некоторые границы уровня, такие как стены или земля, эти объекты никогда не двигаются и для физического движка являются одним целым. Для движка это объект, имеющий коллайдер, не используемый как триггер и не имеющий Rigidbody. Такие объекты, сколько бы их не находилось на сцене, движок подсчитывает единожды и не обращается к ним при пересчете физики в каждом time step, определенным для физики. То есть допустим, если вы двигаете скриптом transform объекта, имеющий коллайдер, но не имеющий Rigidbody, движку приходится пересчитывать абсолютно все статические объекты, чтобы вновь построить сцену, это конечно же не эффективно для производительности.

2) Кинематические объекты - объекты, выполняющие роль статических объектов, но которые мы все же двигаем/вращаем обращаясь к ним через скрипт. Допустим это секретная стена, отодвигающаяся при определенном действии, но в обычном состоянии это типичная стена, как и все стены уровня. Для движка это объект, имеющий коллайдер, не используемый как триггер, но имеющий Rigidbody, настроенный как Kinematic. На этот объект, хоть он и имеет Rigidbody, не будут воздействовать внешние силы (гравитация или столкновения), в то же время он будет останавливать любые динамические объекты, столкнувшиеся с ним. Хоть этот объект и выполняет функцию статического объекта, все же движком он обсчитывается отдельно - всегда используйте для объектов, которые выполняют роль статических объектов, но все же изменяют свое положение в пространстве этот способ, так же перемещая их обращайтесь к их rigidbody, а не transform, это опять же даст правильный просчет физики при их перемещении. Скажем динамический объект, стоящий на кинематическом объекте, который двигается, будет двигаться вместе с ним. Обращение же к transform двигало бы кинематический объект, но не затрагивало бы стоящий на нем динамический объект.

3) Динамические объекты - это объекты, подверженные воздействию гравитации и воздействию других динамических объектов, т.е. они взаимодействуют со всем как настоящий физический объект. Для движка это объект, имеющий коллайдер, не используемый как триггер и имеющий Rigidbody, не помеченный как Is Kinematic. В игровом мире это может быть игрок, стрела пущенная им или допустим коробка, которую можно толкать. У таких объектов можно отключать воздействие гравитации, но они так же будут взаимодействовать с окружающим миром, их все еще можно будет толкнуть, хоть они и будут висеть в воздухе, как какой нибудь статический объект, если ранее им не придали ускорение.

4) Триггеры - все типы объектов могут быть триггерами, для этого в их коллайдерах должно быть указано что это триггер. Триггеры не участвуют в столкновениях, они будут проходить сквозь любые физические объекты, как и другие физические объекты буду проходить сквозь них, во всем же другом они будут так же реагировать на силы, такие как гравитация, если это динамический триггер-объект и тд. При событии OnTriggerEnter движок получает гораздо меньше данных, чем при событии OnCollisionEnter, это связанно с тем, что при событии OnCollisionEnter создается массив со всеми данными физического столкновения, в то время как для события OnTriggerEnter передается только ссылка на коллайдер вошедший в него, что конечно же менее ресурсозатратно. Советую всегда использовать для таких объектов как снаряды триггеры, если конечно вы не используете массив с данными о столкновении в своих целях. Триггеры активно используются в скриптинге и нужны для регистрации попадания в чего либо или регистрации что что-либо входит в них, конечно же работают они только с физическими объектами (имеющими коллайдер или триггер-коллайдер).

Триггером так же может быть объект вообще не имеющий графической части, используясь в виде триггер-зоны (что кстати в играх используется чаще), как и сам коллайдер может быть просто невидимым барьером.
Коллайдеры могут быть разных форм, рекомендуется использовать сочетание более одного примитивного коллайдера, если форма объекта сложная, на один объект можно назначить несколько коллайдеров. Рекомендуется либо вообще отказываться от Mesh коллайдера, либо использовать специально созданный хитбокс под модель, с минимальным количеством полигонов. Использование высокодетализованных Mesh коллайдеров может крайне сильно загрузить систему, задумайтесь перед их использованием. Использование Mesh коллайдеров для статических объектов не так сильно нагружает систему, если конечно вы используете их правильно и не обращаетесь к ним в течении работы программы.

Продолжение

Правка: 10 мар. 2017 2:08

ZlotenПостоялецwww9 мар. 201710:07#1
Продолжай.
coremissionПостоялецwww9 мар. 201714:36#2
Продолжайте, хорошая статья
alexzzzzПостоялецwww9 мар. 201717:43#3
Tokarn
> Жду отзывов, нужно ли продолжать тему и тп.
Продолжай, только добавь чуть оформления: пустые строки между абзацами, заголовки жирным и т.п.

> Обращение же к transform, по сути просто "телепортирует" объект без
> использовании физики, даже если это выглядит гладко, его движение состоит из
> тысяч "телепортаций", вместо настоящего движения.

Самая наглядная демонстрация того, чем тысяча маленьких "телепортаций" отличается от движения с использованием физики (сразу это не очевидно):

Если поставить на сцену стол (как динамический или кинематический rigidbody), на него сверху положить коробочку (как динамический rigidbody) и начать потихоньку двигать стол, то

- Если двигать стол через transform.position или rigidbody.position, он будет уезжать из-под неподвижной коробочки; и когда уедет совсем, коробочка упадёт.

- Если двигать стол через rigidbody.MovePosition(...), коробочка поедет вместе со столом.

[исправил ошибку с rigidbody.position]

Правка: 9 мар. 2017 22:20

clcПостоялецwww9 мар. 201719:39#4
alexzzzz

в юнити физика по мешу считается? примитивы есть? с примитивом стол будет летать, а остальное не должно двигаться

arcturgrayПостоялецwww9 мар. 201720:06#5
Хоть этот объект и выполняет функцию статического объекта, все же движком он обсчитывается отдельно - всегда используйте для объектов, которые выполняют роль статических объектов, но все же изменяют свое положение в пространстве этот способ, так же перемещая их обращайтесь к их rigidbody, а не transform.

В документации сказано использовать для кинематиков именно transform. Хотя там так же приводятся примеры, как можно кинематик двигать через rigidbody.MovePosition. Так что можно двигать как угодно. Плюс, надо заметить, что кинематики, независимо от того, как ты их двигаешь, проходят сквозь другие кинематики и сквозь статические коллайдеры.

Если использовать Mesh Collider'ы, то гораздо лучше делать их выпуклыми.

А вообще физика в Юнити ведь простая. Там документация достаточно хорошая.

TokarnПостоялецwww10 мар. 20171:54#6
Продолжение о 3D физике
У новичков часто бывает так, что при очень быстром движении объектов, они могут пролететь небольшое препятствие насквозь, не среагировав на него должным образом.

Случается это по нескольким причинам:

Во первых для правильного расчета физики, Rigidbody объектов должны быть настроены правильно.
За расчет физики столкновений отвечает опция Collision Detection. По умолчанию эта опция находится в состоянии дискретного расчета - это позволяет производить расчет физики с минимальными затратами и обычно удовлетворяет все потребности в физике, но она не годится для быстродвижущихся объектов.

Есть три вариации, в которой может находится опция Collision Detection:
1) Discrete - установка по умолчанию. Оптимизированный расчет физики, подходящий для большинства нужд. Допустим он подойдет к коробке, бутылке с зельем или любому другому незначительному элементу окружения, являющимся физическим объектом. Так же это обычно подходит и для кинематических объектов.
2) Continuous - Более детальный просчет физики для быстродвижущихся объектов, взаимодействующих со статическими объектами.
3) Continuous Dynamic - Еще более детальный просчет физики для быстрых объектов, взаимодействующих с другими быстрыми объектами.

Во вторых вы должны правильно подбирать временной период расчета физики, именуемый Fixed Timestep. По умолчанию он установлен в значение 0.02
Чтобы изменить его нужно войти в настройки времени, для этого в верхнем меню перейдите следующим путем Edit -> Project Settings -> Time
Параметр Fixed Timestep именно то что нам надо.
Обычно достаточно значения по умолчанию, но для разработки шмапов (shoot'em ups), я уменьшаю временной промежуток в двое, значение 0.01 вполне работает.
Изменяя Fixed Timestep вы изменяете не только время просчета физики, но и время вызова функции FixedUpdate. Помните это! Все ваши скрипты с FixedUpdate будут выполняться чаще, а значит и сильнее загружать систему, к тому же этому поспособствует и более детальный просчет физики.


Продолжение

Правка: 13 мар. 2017 2:36

TokarnПостоялецwww10 мар. 20174:14#7
Немного отойду от движка и коснусь процесса разработки.
Как правило новичок садится за создание игры с уже готовой игрой в голове и пытается воплотить все её аспекты, все эти уровни, скиллы, громадную тонну оружия, экипировки и процедурный мир, да еще и населенный NPC.
Что происходит в этом случае? Он сталкивается с масштабом работы. А что он делает когда понимает что сам не сможет вывезти проект? Идет за командой, перед эти вероятно накачав кучу готовых ассетов и предприняв некоторые попытки склеить все это в одно.
Будет ли он успешен, даже если найдет толковых в своей области специалистов, да еще и на энтузиазме? На 85% нет!
Почему же? Все дело в построении процесса разработки. Масштабный проект требует особого построения процесса разработки, умение такого подхода у новичка отсутствует.
Что же происходит без построения процесса разработки? Мы пичкаем проект излишним, мешающим оценке, контентом. Все эти нагромождения игровых возможностей мешают и отвлекают от создания ядра игры. В итоге всё разваливается извергаясь кучей багов или умирает еще в зародыше.
Как же поступать при старте разработки своего первого проекта? Действовать нужно еще до старта. Внимательно пройдитесь по геймплею будущей игры и выделите элементы, которые составляют ядро игры.
Все первое время будет уделено именно его реализации. Является ли ядром "покупка новой тачки"? Нет! Когда вы создаете ядро, рано говорить даже о моделях и текстурах, это скорее будет набор геометрических фигур, выполняющих нужную роль в игровом процессе. На чем вам нужно сконцентрироваться это на самых базовых функциях. Если вам все еще не понятно, представьте то, без чего вы не сможете выжить: кислород, вода и пища, способность добывать их. То же и для игры: передвигаться, примитивно взаимодействовать с окружением и тп.

Ядро игры (или минимальный жизнеспособный продукт), обычно состоит из минимальных геймплейных действий: движение, стрельба, получение урона. Подробно об этом неплохо рассказывается в этом ролике:

Создав его и убедившись, что все работает как надо, можно передвигаться дальше и шаг за шагом минимально реализовывать игровые возможности: Подбор оружия? хорошо, но не нужно сразу делать 20 видов оружия, вы этим займетесь позже, создав фундамент двигайтесь дальше, создав следующий уровень фундамента игры и следующий, оттачивая минимальный набор возможностей.
Крайне рекомендую для первого проекта брать небольшой проект. Не думайте что небольшой - значит не интересный, все зависит только от вас. Толковый геймдизайнер может взять пространство 100 на 100 пикселей и сделать в нем игру, которая затянет на месяца, что говорить о громадном виртуальном пространстве, доступном вам? Просто поубавьте амбиции и включите воображение, ограничивая его рамками проекта.

Правка: 10 мар. 2017 4:48

TokarnПостоялецwww13 мар. 20172:35#8
Продолжение №2 о 3D физике
Подробнее о правильной настройке Mesh коллайдера.

По умолчанию, когда мы добавляем Mesh коллайдер к объекту, движком он опознается как некий физический каркас, для примера его можно сравнить с плоскостью из примитивов Unity, только развернутой в объемную фигуру.
Т.е. внутри фигуры будут пустоты, не обрабатываемые физическим движком и в связи с этим при использовании такого коллайдера применимо к динамическим объектам, могут возникнуть различные казусы.
Использование Mesh коллайдера в таком виде отлично подходит под статические объекты (например мы могли бы смоделировать уровень в 3D редакторе и упрощенную сетку к нему и использовать её в качестве mesh коллайдера) - такое использование будет достаточно оптимизированным и не нагружать лишний раз систему, но использование Mesh коллайдера для динамических объектов требует другой подход.

Для использования Mesh коллайдера для динамических объектов нам нужно чтобы коллайдер имел информацию не только о его каркасе, но и внутреннем его заполнении, а это значит он должен быть "выпуклым" коллайдером.
Чтобы настроить Mesh коллайдер как "выпуклый" коллайдер, нам нужно указать в настройках компонента опцию "Convex". Это кстати еще и сопроводится визуальным отображением гизмо коллайдера в окне редактора сцены.
Convex Mesh коллайдер так же позволяет использовать коллайдер как триггер. Помните, что Mesh коллайдер должен быть минимально детализованным, чтобы не нагружать систему. В Unity выпуклые коллайдеры ограниченны 255 полигонами (в юнити используются треугольники и все прямоугольные полигоны конвертируются в них, учитывайте и это при построении будущего коллайдера в 3D редакторе).

Продолжение

Правка: 24 мар. 2017 2:52

DanielDemПостоялецwww17 мар. 201714:42#9
Хорошо пишите, расскажите про составные коллайдеры. Как правильно их применять в иерархии игровых объектов
NickulusПостоялецwww17 мар. 201717:21#10
Tokarn
> Масштабный проект требует особого построения процесса разработки, умение такого
> подхода у новичка отсутствует.
Tokarn
> Создав его и убедившись, что все работает как надо, можно передвигаться дальше
> и шаг за шагом минимально реализовывать игровые возможности: Подбор оружия?
> хорошо, но не нужно сразу делать 20 видов оружия, вы этим займетесь позже,
> создав фундамент двигайтесь дальше, создав следующий уровень фундамента игры и
> следующий, оттачивая минимальный набор возможностей.
  При неограниченных финансах или в стране эльфов эта схема наверно работает - дальше заказываем концепты, по ним нам моделят-текстурируют-анимируют, нам остается только менять кубики на модели, высказывать замечания о недостатках - которые тут же устраняются, ляпота.
  Но в реальности - создали мы геймплей на кубиках, про выживание с белыми медведями - а максимум умений моделирования-текстурирования - простой танчик, анимации - вращение башни. Денег пусто. Весь этот геймплей - как крутые тренерские наработки сборной по футболу, при том что игроки банально в ворота не попадают.
TokarnПостоялецwww24 мар. 20172:51#11
Триггер-коллайдеры 3D
Подробнее о взаимодействии триггеров и правильное их применение в иерархии игровых объектов.

Представьте себе такую ситуацию, в которой бы вы, создавали космический шутер или любую другую игру, использующую похожую механику.
В процессе производства, вы решаете использовать триггер-коллайдеры, вместо коллайдеров, для регистрации попаданий по игровым объектам, ведь это упростит физические расчеты и лишний раз оптимизирует игру.
Вы создаете идеально работающий прототип игры, в котором ваш корабль успешно уничтожает противника, сталкивается с препятствиями и получает повреждения от пуль противника.
В вашей игре есть простые правила: пули наносят урон, а препятствия, такие как метеориты, уничтожают ваш корабль при столкновении.

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

Что же случилось? Вместо летающей боевой крепости, вы получаете огромную неуклюжую космическую мишень для астероидов и других опасностей! Щит блокирует пули, как это и прописано в скрипте, столкновения же с препятствиями должны игнорироваться, а это не происходит! Почему? Ведь в скрипте прикрепленном к щиту вообще не было и строчки касающейся препятствий?

Такое может произойти по одной причине: на объект игрока прикреплен скрипт, определяющий пересечение с коллайдером препятствий.
Дело в том, что физический движок считает родительский объект и все прикрепленные к нему дочерние объекты с коллайдерами одним целым. То есть ваш корабль будет считать, что препятствие столкнулось с ним, даже если оно задело дочерний к нему силовой щит, в то время, как само препятствие зарегистрирует пересечение только с триггером дочернего объекта щита и не будет регистрировать пересечение с триггером корабля игрока, до тех пор пока не коснется его самого. Стоит так же отметить что в такой ситуации, когда препятствие сначала бы коснулось триггера силового щита, а затем самого корабля игрока, триггер корабля игрока зарегистрировал бы два пересечения с триггером препятствия и регистрировал бы их больше, если бы дочерних к нему объектов с триггерами было бы несколько.

Конечно же наиболее простым решением такой проблемы было бы прикреплять скрипт, регистрирующий столкновения на сами префабы препятствий, а так же присваивать и игнорировать в коде тег щита игрока, если ваш скрипт на столкновения этого требует.


И так:

  • Родительские объекты реагируют на столкновения других объектов с триггерами их дочерних объектов ровно так же, как и на столкновение с их собственным триггером.
  • Родительский объект, будет регистрировать больше одного касания с другим объектом, если тот заденет несколько дочерних объектов с триггерами, либо дочерний объект и триггер-компонент родительского объекта.
  • Другой объект реагирует на отдельные объекты такой группы по разному: для него это разные объекты, даже несмотря на то, что они заключены в отношение родительский-дочерний (т.е. корабль и щит для метеорита - отдельные объекты).
  • Несколько компонентов триггер-коллайдеров на одном объекте, составляют единый сложный триггер-коллайдер и реагируют как один коллайдер (не будет более одной регистрации входа в триггер, кроме тех случаев, когда объект выйдет из зоны действия всех компонентов триггера и войдет в него снова).

    Продолжение

  • Правка: 26 мар. 2017 1:56

    TokarnПостоялецwww26 мар. 20171:55#12
    Физика 2D или Box2D в Unity
    По сути разработчики постарались максимально приблизить работу с 2D физикой к работе с 3D физикой.
    В работе со скриптами используются схожие функции, разве что теперь вы по большему счету будете работать с Vector2 координатной системой, а коллайдеры заменены на их "плоские" варианты.

    Если не углубляться в подробности, использование Box2D, в подавляющем большинстве случаев будет более производительным решением, нежели использование полноценной 3D физики.
    Конечно такой вариант не подойдет для использования в исконно 3D играх, таких как FPS и тп, но большинство проектов, которые часто выполняются в 3D, отлично будут работать и с 2D расчетами.

    Использование 2D физики не означает что вы привязаны только к скучным вращениям объектов вокруг своей оси только по часовой стрелке или против и уж тем более не означает что вы привязаны только к использованию спрайтов.
    Вы так же можете успешно использовать 2 вида камеры в проекте: двухмерную ортографическую камеру и полноценную перспективу.

    Скажем вы захотели сделать вращающийся произвольно объект (скажем метеорит). Как же правильно использовать инструментарий, чтобы случайно не наплодить багов в расчете 2D физики?
    Применять вращение напрямую к объекту не разумно: представим что метеорит состоит из игрового объекта, имеющего в компонентах его визуализацию, 2D коллайдер и 2D rigidbody.

    Так как мы не можем полноценно вращать объект обращаясь к Rigidbody2D, мы будем обращаться к его Transform. Что же получится?
    2D коллайдер будет вращаться вместе с объектом, а учитывая что он "плоский" для физического движка, то по идее, вращаясь вместе с объектом, он будет просто деформироваться и становиться то уже, то снова шире.
    Объекты сталкивающиеся с ним могут проваливаться в его текстуру, а то и вовсе пролетать его насквозь.

    Решением такой проблемы будет создание дочернего объекта, содержащего визуализацию нашего метеорита, на него и будет назначаться скрипт, который будет вращать визуальную часть метеорита, не трогая при этом его физическую часть.

    bodjaПостоялецwww26 мар. 201716:03#13
    Tokarn
    Не слишком ли замудрено для новичков? :)

    Предлагаю подытожить.
    1. Физдвижок хорош тем, что может посчитать коллизии в геометрии, причем сделать это очень быстро используя аппаратные возможности видекарты, учитывая что Юнька использует Физикс, на Радеонах это будет работать как на пылесосе :)

    2.  Rigidbody годятся только для красивого разлетания ящиков\шариков, забор не поломать, дерево не повалить и т.д. , настраивать сложную физику будет одно мучение, короче учите математику, нередко можно обойтись простыми формулами дополнив анимациями.

    3. Что бы пули не пролетали стены, делайте проверку пересечения луча с мешем, возвращая дистанцию и вектор нормали полигона, так вы узнаете весь маршрут движения пули со всеми рикошетами еще до выстрела :)

    4. Физдвижок сначала проверяет bounding box-ы мешей, будет хорошо если разобьете\соберете геометрию коллизий на секции для больших локаций. В идеале должна быть карта обьектов, что бы сразу выходить на проверку нужного меша, но это уже совсем другая история :)

    TokarnПостоялецwww5 мар. 20184:38#14
    solomenny
    Немного занят, чтобы тестить на работоспособность и тем более реализовывать проверку расстояния до игрока и обращаться к его аниматору, включая анимацию, но если ничего не найдешь
    + Показать

    Правка: 5 мар. 2018 4:52

    Страницы: 1 2 Следующая »

    / Форум / Программирование игр / Общее

    2001—2018 © GameDev.ru — Разработка игр