как сделать чтобы объект не проходил сквозь стены в unity
Unity Отключить ходьбу персонажа при обнаружении стены
Есть персонаж, есть земля, на обоих висят коллайдеры. Перемещение через transform.position
Когда персонаж подходит к стене с зажатой клавишей, то он пытается передвинуться в сторону стены, но его выталкивает и получается дергание персонажа.
Я попытался решить проблему так, проверяю через OverlapCircleAll есть ли рядом стена, если есть, то идти нельзя. Однако все-ровно одно-два дрожания в самом начале осталось. Как это исправить и как альтернативно можно решить данный вопрос?
2 ответа 2
Причина в том, что у вас вместе с коллайдером идет rigidbody(ну скорей всего). Когда в Update или LateUpdate вы перемещаете объект через transform, на 1 кадр объект попадет внутрь другого коллайдера, а в начале след кадра, физика вытолкнет обратно его, отсюда и дергание) Есть 3 способа решения: 1. Двигать в FixedUpdate
Двигать в Update/LateUpdate используя velocity или AddForce на rigidbody
Вектор смещения(dir)
Длина вектора смещения(lendir)
Половина размера коллайдера(ext)(использовать радиус у «сфероподобных»(capsule всякие), ну или большую сторону для «угловатых»(box. ))
Кидать райкаст вдоль dir.normalize*(lendir+ext)
Если райкаст попадет во что-нибудь, вычислить расстояние до точки попадания(distToPoint), и если (distToPoint-extС)
Оружие проходит через стены
Помощь в написании контрольных, курсовых и дипломных работ здесь.
Персонаж проходит сквозь стены
Здравствуйте! Прошу помочь, персонаж проходит сквозь стены как можно исправить? (Вид игры сверху.
Свет проходит сквозь стены
Кто знает помогите. Все настройки перерыл, в интернете вся инфа старая. Вот закрытая комната, за.
Объект частично проходит сквозь стены во время движения
Код передвижения: using System.Collections; using System.Collections.Generic; using UnityEngine;.
Как запретить объекту проходить через стены в navmesh?
Привет. При написании курсача возникла проблема. У меня есть 3д модель корпуса. Стены, двери, пол.
Решение
Можно сделать анимацию поднятия в верх либо по видео попробуй сделать.
Помощь в написании контрольных, курсовых и дипломных работ здесь.
Проблема стрельбы врагов через стены по игроку в TDS Unity2D (игра с видом сверху)
Здравствуйте уважаемые знатоки). У меня враги стреляют в меня через стены, а мне этого не надо. Я.
Как с помощью Audio.get VK получить список треков со стены пользователя или стены сообщества?
Всем доброго времени суток! Вопрос, скорее всего банален, но что то тем подобных на форуме не.
Скрипт для очистки стены СоцСети через консоль браузера
В JS я ни разу не специалист, даже не любитель, но надеюсь на совет. Итак. Достаточно давно был.
Как предотвратить прохождение коллайдеров друг через друга?
у меня возникли проблемы с хранением игровых объектов внутри замкнутого пространства. Когда они достигают края, происходит какое-то мгновенное отталкивание, но затем они проходят прямо сквозь стену.
Я использую Box Collider на игроке и сетчатый коллайдер для стены уровня. У меня возникли проблемы с персонажем игрока (космический корабль), что движение контролируется игроком. И с снарядами, которые ведут огонь и забывают двигаться с постоянной скоростью.
это мой код движения для моего игрока. Он работает в
7 ответов
столкновение с быстро движущимися объектами всегда является проблемой. Хороший способ обеспечить обнаружение всех столкновений-использовать Raycasting вместо того, чтобы полагаться на физическую симуляцию. Это хорошо работает для пуль или небольших объектов, но не даст хороших результатов для больших объектов. http://unity3d.com/support/documentation/ScriptReference/Physics.Raycast.html
псевдо-codeish (у меня нет завершения кода здесь и плохой памяти):
У меня есть прототип пинбола, который также дал мне много проблем в тех же областях. Это все шаги, которые я предпринял, чтобы почти (но еще не полностью) решить эти проблемы:
для быстро движущихся объектов:
установите интерполяцию rigidbody в «интерполяцию» (это не влияет на фактическое моделирование физики, но обновляет рендеринг объекта должным образом-используйте это только для важных объектов с точки зрения рендеринга, таких как игрок или пинбол, но не для снарядов)
установите обнаружение столкновений в непрерывное динамическое
прикрепить скрипт DontGoThroughThings (https://www.auto.tuwien.ac.at/wordpress/?p=260) к вашему объекту. Этот скрипт умело использует решение Raycasting, которое я опубликовал в своем другом ответе, чтобы оттянуть оскорбительные объекты до точек столкновения.
установите минимальное проникновение для штрафа до очень низкого значения. Я установил свой 0.001
установите счетчик итераций решателя в более высокое значение. Я установил свой на 50, но вы, вероятно, можете сделать хорошо с гораздо меньшим.
все, что будет иметь штраф в performace, но это неизбежно. Значения по умолчанию мягки по производительности, но на самом деле не предназначены для правильного моделирования небольших и быстро движущихся объекты.
Как насчет установки обнаружения столкновения rigidbody в непрерывно или Непрерывный Динамический?
поэтому я не смог заставить коллайдеры сетки работать. Я создал составной коллайдер, используя простые коллайдеры, и он работал точно так, как ожидалось.
другие тесты с простыми коллайдерами сетки вышли то же самое.
похоже, что лучший ответ-построить составной коллайдер из простых коллайдеров коробки/сферы.
для моего конкретного случая я написал мастер, который создает составной коллайдер в форме трубы.
другим решением может быть вычисление координат (например, у вас есть мяч и стена. Мяч попадет в стену. Поэтому вычислите координаты стены и установите процесс удара в соответствии с этими кординатами)
1.) Никогда не используйте сетчатый коллайдер. Используйте комбинацию box и capsule collider.
2.) Проверьте ограничения в RigidBody. Если поставить галочку заморозить позицию X, то она пройдет через объект по оси X. (То же самое для оси y).
старый вопрос, но, возможно, это поможет кому-то.
перейдите в настройки проекта > Время и попробуйте разделить фиксированный шаг времени и максимально допустимый шаг времени на два или четыре.
У меня была проблема, что мой игрок смог протиснуться через отверстия меньше, чем игроки коллайдера, и это решило ее. Это также помогает остановить быстро движущиеся объекты.
Правильная реализация передвижения персонажа
Почему один обьект проходит сквозь другой хотя у меня есть коллайдеры на обоих обьектах?
Почему мой персонаж во время движения проходит сквозь другой обьект, а потом его откидывает назад?
Как реализовать передвижение персонажа в Unity3d правильно?
Почему так часто используется передвижение через transform.position и почему это неправильно?
Почему мой персонаж движется с разной скоростью если проседает FPS?
Почему двигать персонажа через смену transform.position неправильно?
Как сделать прыжок от пола, но так что бы персонаж не мог бесконечно взлетать
Все эти вопросы, фактически, являются одним единым вопросом, который слишком уж часто встречается у начинающих.
Заодно создал тэг unity3d-faq
1 ответ 1
Перед прочтением важно знать
Хоть я здесь и разбираю в т.ч. нефизическое движение, я настоятельно рекомендую использовать ФИЗИЧЕСКОЕ движение. И переходить на нефизическое только в исключительных ситуациях.
Я буду использовать здесь 2 термина: «телепортация» и «плавное движение». В моем понимании:
Есть люди у которых мнение отличается.
Учтите, что все что написано ниже упирается в верхние значения терминов, а не эти.
Двигать обьекты в игровых движках можно следующими способами:
используя физический движок (движение обусловленное физической моделью игрового движка)
Движение реализуемое через CharacterController (здесь пока что не рассматривается т.к. новички в его сторону вообще не смотрят, может, позже распишу)
Новички очень часто использую телепортацию на каждом кадре, что есть критически неправильным подходом. Потом на SO появляются кучи клонов вопросов вроде «почему персонажа дергает возле стены?» или «почему он проходит сквозь стену?» или «почему пуля не всегда наносит урон?» и подобные.
Нужно запомнить всего одно правило: Двигать/поворачивать через присвоение transform.position / transform.rotation нельзя. Это порождает проблемы. В любом случае это вам вылезет боком.
Пример правильной реализации движения:
( на примере обьекта-шара )
в отличии от пестрящих дичью форумов, в т.ч. сервисе вопросов/ответов от юнити. Там в таких темах слишком часто пишут ответы те люди, которые понятия не имеют о правильном подходе.
Связанные с темой понятия:
Если обьект не обладает физическими свойствами (не имеет RigitBody) эти параметры и методы можно использовать для НЕфизического передвижения.
Например поворот камеры.
Или крутящийся куб на небосводе.
Мы не получим дергающуюся картинку при проседании кадров если сделаем НЕФИЗИЧЕСКОЕ движение правильно:
мы присваиваем в новую позицию:
Про физические свойства движения.
мы разово задаем вектор скачка. Только 1 долю секунды. Но он будет изменятся во времени автоматически равномерно уменьшаясь под силой тяжения. Пока не станет нулевым (верхняя точка прыжка), а потом не пойдет в минус по Y (падение), а потом не упадет на землю и не отскочит от нее (снова плюс по Y ) и так до полной остановки физической скорости обьекта на земле.
Если девайс с игрой сильно загружен, вызов методов Update() / FixedUpdate() тоже может просесть в скорости. И если в физике это учтено и без нас, то сейчас мы делаем НЕ физическое движение и именно по-этому это нужно учитывать добавлением даного множителя.
Но и без использования даного множителя у нас не появится проблем с провалами сквозь стены. Это просто фикс скорости.
Пример простой но хорошей НЕФИЗИЧЕСКОЙ реализации кода движения на примере персонажа.
Если в прошлом примере мы двигали шар, то было допустимо его толкать используя физ.модель. То есть мы использовали AddForce() для этих целей.
Давайте актуализируем этот код под даного персонажа. Мы заменим физический толчек обьекта на не-физическое, но ПЛАВНОЕ перемещение обьекта в пространстве:
С этим кодом мы получим такой результат:
С такой реализацией у нас не будет проблем вроде скачков скорости на проседании или повышении количества FPS, проваливаний, дерганости, прохождения сквозь стены или других неожиданностей.
Так же можно добавить анимацию бега на нашего персонажа (ну если бы это был не куб).
Но как же реализация на физике?
Да, можно подобное реализовать и на физике.
Наша прошлая версия скрипта имела несколько недостатков. А именно:
Давайте поместим на наш куб CapsuleCollider (минимальное торможение из-за силы трения) и заблочим в rigitBody rotateX и rotateZ (что б наш персонаж не падал на бок).
А потом нацепим на него вот этот скрипт:
Вы видите эту плавность, как будто человек бежит, останавливается, бежит в другую сторону? Красота!
А теперь вернитесь к прошлой гифке и присмотритесь. Движение совсем не такое 🙂 Там как буд-то рукой двигают шахматную фигуру по доске.
Ну и описанные выше баги поведения были пофикшены с такой реализацией.
Можно добавить еще физический материал нашему персонажу и откоректировать его поведение.
Вообще улучшать реализацию можно до бесконечности. Но, думаю, основные проблемы СПОСОБОВ ПЕРЕДВИЖЕНИЯ с которыми вы столкнетесь, я затронул 🙂
Оптимально использовать именно передвижение на базе физики.
Пытайтесь использовать исключительно физическое передвижение.
Реализация нестандартной физики движений.
Одним из моих любимейших примеров нестандартной физики движения является игра Ori and the Blind Forest
Такое перемещение/такие прыжки невозможно сделать на основе стандартной физики. Вероятнее всего, это делалось через нефизическое перемещение + костыли для получения нужных эфектов.
Сначала разрабатываются концепты движения. Они делаются в любом видеоредакторе с примитивными фигурами. Вот пример (если станет недоступным искать можно по Ori and the blind forest Enemy Concepts ) :
Обратите внимание на то, то здесь прорисовано не только перемещение обьекта, но и его вытягивания/сжатия. Изменения формы во время любого взаимодействия с внешним миром. В т.ч. выстрелы так же влияют на форму. А так же что указываются радиусы опознавания главного героя каждым отдельным врагом.
Костыли для каждого персонажа/врага свои собственные. Это делается что бы каждый из них обладал своей уникальной физикой. Сделать это на общей физике навряд ли возможно.
Движение реализовано «правильно» но предмет все равно пролетает сквозь стену
ДАЖЕ если вы реализовали физическое передвижение вашего персонажа, все равно может случится такое, что просчет CollisionDetect может проходить с ошибками. Такое бывает.
Для таких случаев есть настройки отвечающие за обработку CollisionDetect в настройках самого RigitBody.
Желательно такого не делать т.к. это негативно сказывается на производительности. Чем на большем количестве обьектов вы меняете эти настройки, тем более вероятно что вы делаете какую-то дичь, которую делать совсем не нужно. Считайте это спасательным кругом, а не панацеей. А если вы так будете делать, то рано или поздно вы прийдете на SO с вопросом почему игра тормозит, вас попросят показать код и ничего не найдут просто потому, что проблема тормозов не в коде. И намучаетесь вы с оптимизациями ой как сильно.
Как сделать чтобы игрок не проходил сквозь объекты unity
Unity TopDownShooter проблема с прохождением сквозь спрайты
Только начинаю работать в Unity. Делаю простой topdown shooter. Сделал ходьбу, стрельбу, слежение камеры за игроком, но не могу реализовать кое что.
А именно мой персонаж проходит сквозь стену(спрайт). Помогите, пожалуйста, исправить это. Искал проблему в YouTube, разных форумах, но нигде об этом не говорится. Может вы хотя бы поможете.
Вот скрипт ходьбы + стрельбы
А также помогите, чтобы когда мой персонаж ходил его не дергало, а все плавно было.
Дубликаты не найдены
Кидаешь на стены коллайдер2д, на перса коллайдер2д и ригидбоди2д, в ригидбоди ставишь гравити в нуль. Усе. На первое время тебе пойдет)
А чтобы перс не дрыгался при ходьбе, перенеси движение из фикседа в обычный update с обычной дельтой.
Блин, огромное спасибо тебе, а то я правда по всем форума чекал, как делать эту стену и на ютубе много роликов смотрел и про движение,столкновение,в общем про коллайдеры, но никто не мог нормально сделать это. Начал смотреть видосы на английском языке, там все нормально реализовано, но половина скрипта пропущена и не мог найти ошибку. Спасибо.
Спрайты? Не, я спрайт не люблю. Мне больше грейпфрутовый сок нравится.
а как именно сделать? Я добавляю к моему персонаж 2d collider и к самому спрайту, также добавляю rigidbody2d(отключаю gravity), но тогда спрайт улетает, а мне нужно, чтобы он был на одном месте и мой персонаж не могу проходить сквозь него
Так ты не ставь rgbody на спрайт и не будет улетать
добавил скрины в пост, смотрите
Убрал тригеры и поставил в rgbody dinamic. Теперь стена от меня улетает, когда пытаюсь с ней столкнуться. А нужно, чтобы она была на месте.
У стены убери rigidbody, либо переключи на kinematic (если её почему-то надо двигать) и посмотри уже наконец гайды для начинающих на том же ютубе, повторяя пошагово то, что там показывают.
колайдеры на персонаже и стене,но персонаж все равно проходит сквозь стену
ANEID | RPG #1 — делюсь первыми геймплейными наработками проекта
Наконец-то могу поделиться первыми результатами работы над геймплейной составляющей моего скромного проекта. От вас, дорогие друзья, жду ваших замечаний. С интересом послушаю и предложения, поскольку сам не в силах пощупать все игры на предмет поиска в них крутых механик, поэтому обращаюсь к мудрости Пикабу.
p.s. на другом ресурсе мне уже сказали про небольшой перебор с блюмом, однако это издержки демо-комнаты. «Родная» локация данного пост-процесса выглядит адекватно:
От наброска в паинте до демоверсии
Вводный материал.(Вода)
Желания создавать игры пришло ко мне довольно в раннем возрасте. Вдохновившись одной браузерной игрой я начал активно искать информацию связанной с разработкой игр и приложений. На тот момент времени, о процессе разработки игр я знал на неком абстрактном уровне – есть программы именуемые движками в которых происходит соединительный процесс моделей, звуков, анимации и кода и есть программы, так сказать второго эшелона, программы в которых непосредственно создаётся ранее описанный контент.
Небольшое, отступление: на дворе 15 год, сельская глушь, за столом устаревший, даже на то время компьютер, на окне подвисший модем с одна-гиговым объёмам помесячного трафика. Именно в таких условиях начался мой путь.
Само собой, не о каких специализированных программах я не знал, но, на моё удивление, их поиск не занял много времени. К моему приходу, сеть уже была полна материалов на тему геймдева и игровой индустрии в целом.
Названия первого движка я вряд ли могу вспомнить, но вот его вес 37мб, хорошо отпечатался в моей памяти. Собственно, общий вес данной программы и стал ключевым фактором выбора, также словосочетание “решение с открытым кодом” внесло свой вклад, моё наивное желание творить навеяло мысль что в случае необходимости я смогу настроить под себя данную программу или даже больше, смогу на её фундаменте выстроить собственный движок. Как же я ошибался…
Параллельно с изучением трёхмерной графики я уже пришёл к движку который использую по сей день – Unity. Какой же восторг я испытал, добавив только – что смоделированный кубический ящик в игровую среду. Добавление физических свойств моему ранее замоделенному объекту и вовсе вызвало некий экстаз. Время вновь шло непозволительно быстро, обломавшись с концепцией сетевого шутера, да-да, как и многие начинающие я не хотел создавать что то простое, мне хотелось делать глобальные проекты которые могли позволить лишь студии гиганты. Изрядно обломавшись, осознав что в реалиях одного человека невозможно создать задуманное я поумерил свой пыл и постепенно пришёл к жанру пост-апокалипсиса. Пару небольших подделок, пару графических экспериментов, огромные амбиции плавно перетекли в пару закрытых дэмок которые не принесли должного результата. Настал момент уныния, раннее задуманная концепция не сработала, техническая часть не доведена до должного уровня а визуальная составляющая на которую делался главный акцент оказалась провальной…
Думаю мне повезло, на фоне маячил релиз одной важной для меня игры, судьбоносно что жанры совпадают. Так, не найдя чем заняться ближайший месяц до релиза ожидаемой игры я вспомнил одну старую концепцию. Что если выстроить визуал игры из палитры ограниченной тремя цветами – чёрный, серый и оранжевый. Так открыв стандартный графический редактор я соединил парочку приглянувшихся изображений. Итог:
Внимание, дабы последующий материал не выглядел набором скриншотов дальнейший текст будет построен примерно так: дата отсчёта (примерная) через какой временной промежуток от начала разработки сделан скриншот, небольшое описание проделанной работы или максимально ёмкий комментарий.
Также, отмечу, я расскажу только своё виденье разработки отдельно от команды.
P.S : Многие скриншотов изначально небыли предназначены для показа широкой публике, поэтому, мне пришлось размыть некоторые элементы изображений.
Начало работы.Построение общей визуальной концепции с помощью спрайтов и простой геометрии.Первые строчки кода. Настройка рендера.
+ изначально, задний фон обладал реалистичным расстоянием — объекты располагались в промежутке от 1 метра до 1км игровых координат. Это привело к тому что при перемещении задний фон менялся очень медленно а иногда и вообще выглядел статично. В дальнейшем и по сей день, максимальной дистанцией отдаления считается значение
300 игровых метров а пропорции подбирались в ручную или с помощью соответствующего инструментария.
Игрок проходит сквозь объект, хотя box collider 2d уже стоит(включен Trigger)
Игрок проходит сквозь объект, хотя box collider 2d уже стоит(включен Trigger)
Проходит сквозь объект.rar (4.86 Мб, 4 просмотров) |
Игрок проходит сквозь клоны объектов
Здравствуйте, я пишу игру и столкнулся с такой проблемой, при создании объектов через instatiate.
Игрок проходит сквозь стену постоянно!
Здравствуйте, у меня есть 2D платформер, в платформере у меня есть игрок, который может ходить, но.
Сделать чтобы игрок ПРОХОДИЛ сквозь объект (2D)
Добрый день! У меня такая задача. Есть игрок у которого есть RigidBody2D и коллайдер и есть.
создай там объект еще один с коллайдером(не триггером, удалив компонент мешрендерер и меш фильтр, что бы он не отображался в сцене в сцене). триггер немного расширь, потому как коллайдер не пропустит игрока в триггер. если триггер сработал (то есть условия по которым можно перейти верны,отключай объект с коллайдером, проходи дальше и грузи другую сцену.
как то так.
Добавлено через 2 минуты
а вообще можно два коллайдера вешать, один пусть будет триггером а другой просто коллайдером. но сам не практиковал такое. не могу сказать насколько рабочее решение
Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.
Объект с RigidBody2D и Collider (неважно box или circle) вращается вокруг своей оси
Если персонажем, на котором висит RigidBody2D и Collider (неважно box или circle), вплотную подойти.
Объект частично проходит сквозь стены во время движения
Код передвижения: using System.Collections; using System.Collections.Generic; using UnityEngine;.
Персонаж проваливается сквозь Edge Collider 2D
Всем доброго времени суток! Объясните почему главный герой после прыжка может провалиться сквозь.
Твердый объект проходит сквозь твердый
Смотрите у меня такая ситуация есть на сцене кубики, подцеплены к ним колайдеры и ригибоди.
Проблема с Box Collider 2D
Всем привет, возникла такая проблема, если box Collider2D соприкосаеться с другим box Collider2D.
Проблема с Box Collider 2D
Всем привет, возникла такая проблема, если box Collider2D соприкосаеться с другим box Collider2D.
Ошибки новичка Unity, испытанные на собственной шкуре
Привет, Хабр. Это снова я, Илья Кудинов, QA-инженер из компании Badoo. Но сегодня я расскажу не о тестировании (этим я уже занимался в понедельник), а о геймдеве. Нет, этим мы в Badoo не занимаемся, разрабатывать компьютерные игры — моё хобби.
Профессионалы индустрии, не судите строго. Все советы в этой статье адресованы начинающим разработчикам, решившим попробовать свои силы в Unity. Многие советы можно отнести к разработке в целом, но я постараюсь добавить в них Unity-специфику. Если вы можете посоветовать что-то лучше, чем предлагаю я — пишите в комментариях, буду обновлять статью.
Я мечтал разрабатывать игрушки с детства. Наверное, уже в далёком 1994 году, когда мне подарили мою первую Dendy, я думал: “Как была бы здолава, если бы вот в этай иглушке было бы ещё всякое классное. ” В средней школе я начал учиться программировать и вместе с товарищем делал свои первые играбельные поделки (ох, как мы их любили!). В институте мы с друзьями строили наполеоновские планы о кардинальном изменении индустрии с помощью нашей совершенно новой темы…
А в 2014 году я начал изучать Unity и наконец-то НА САМОМ ДЕЛЕ начал делать игры. Однако вот беда: я никогда не работал программистом. У меня не было опыта настоящей корпоративной разработки (до этого я всё делал “на коленке”, и, кроме меня, в моём коде никто бы не разобрался). Я умел программировать, но я не умел делать это хорошо. Все мои знания Unity и C# ограничивались скудными ещё на тот момент официальными туториалами. А мой любимый способ познавать мир — делать ошибки и учиться на них. И я наделал их предостаточно.
Сегодня я расскажу о некоторых из них и покажу, как их избежать (ах, если бы я знал всё это три года назад!)
Для того чтобы понять все используемые в материале термины, достаточно предварительно пройти один-два официальных туториала Unity. Ну, и иметь хоть какое-то представление о программировании.
Не засовывайте всю логику объекта в один MonoBehaviour
Что, суть моего совета в том, чтобы не писать гигантские классы, спасибо, Кэп? Нет. Мой совет: дробите вашу логику на атомарные классы ещё до того, как они станут большими. Пусть сначала ваши объекты будут иметь три-четыре осмысленных компонента по десятку строк в коде каждого, но ориентироваться в них будет не сложнее, чем в одном из 50 строк, зато при дальнейшем развитии логики вы не окажетесь в такой ситуации, как я. Заодно появляется больше возможностей для переиспользования кода — например, компонент, отвечающий за здоровье и получение урона, можно прилепить и игроку, и противникам, и даже препятствиям.
Не забывайте про ООП
Каким бы простым ни казалось на первый взгляд проектирование объектов в Unity (“Программирование мышкой, фуууу”), не нужно недооценивать эту составляющую разработки. Да-да, я вот недооценивал. Прямо по пунктам:
При этом C# — такая душка, что позволяет не плодить эти параметры, и вот эти два вызова будут работать идентично:
Изучите Editor GUI
Я этим занялся значительно позже, чем стоило. Я уже писал статью о том, как это может помочь при разработке как программисту, так и геймдизайнеру. Помимо кастомных инспекторов для отдельных атрибутов и целых компонентов, Editor GUI можно использовать для огромного количества вещей. Создавать отдельные вкладки редактора для просмотра и изменения SAVE-файлов игры, для редактирования сценариев, для создания уровней… Возможности — безграничны! Да и потенциальная экономия времени просто восхитительна.
Думайте о локализации с самого начала
Даже если вы не уверены, что будете переводить игру на другие языки. Впиливать локализацию в уже сформировавшийся проект — невыносимая боль. Можно придумать самые разные способы локализации и хранения переводов. Жаль, что Unity не умеет самостоятельно выносить все строки в отдельный файл, который поддаётся локализации “из коробки” и без доступа к остальному коду приложения (как, например, в Android Studio). Вам придётся писать такую систему самому. Лично я использую для этого два решения, пусть и не очень изящные.
Оба они базируются на моём собственном классе TranslatableString :
В нём ещё есть кучка строк с защитой от ошибок и проверки на заполненность полей, сейчас я их убрал для читабельности. Можно хранить переводы как массив, но по ряду причин я всё же выбрал отдельные поля.
Вся “магия” — в методе неявного преобразования в строку. Благодаря ему вы в любом месте кода можете вызвать что-то типа такого:
— и сразу же получить в строке text нужный перевод в зависимости от текущего языка в настройках игрока. То есть в большинстве мест при добавлении локализации даже не придётся изменять код — он просто будет продолжать работать со строками, как и раньше!
Первый вариант локализации очень простой и подходит для игр, где совсем мало строк, и все они расположены в UI. Мы просто добавляем каждому объекту с переводимым компонентом UnityEngine.UI.Text вот такой компонент:
Заполняем все строки переводов в инспекторе — и вуаля, готово!
Кстати, полезная вещь — язык системы игрока (по сути, его локализационные предпочтения) можно получить с помощью, например, вот такого кода:
Пишите подробные логи!
Это может показаться излишним, но теперь некоторые мои игры пишут в лог практически каждый чих. С одной стороны, это дико захламляет консоль Unity (которая, к сожалению, не умеет заниматься никакой удобной фильтрацией), с другой — вы можете открыть в любом удобном вам софте для просмотра логов исходные лог-файлы и составлять по ним любые удобные вам отчёты, которые помогут заниматься как оптимизацией приложения, так и поиском аномалий и их причин.
Создавайте самодостаточные сущности
Я делал глупости. Предположим, мы хотим как-то хранить настройки различных уровней какой-то игры:
Мой первоначальный подход был такой: Mission хранит в себе только параметры, а MissionController занимается всеми прочими запросами. Например, чтобы получить лучший счёт игрока на определённом уровне я использовал методы вида
Казалось бы, всё работает исправно. Но затем таких методов становилось всё больше, сущности разрастались, появлялись прокси-методы в других классах… В общем, наступил спагетти-ад. Поэтому в конечном счёте я решил вынести все методы для работы с миссиями в саму структуру Mission и стал получать рекорды миссии, например, таким образом:
что сделало код гораздо более читабельным и удобноподдерживаемым.
Не бойтесь использовать PlayerPrefs
Во многих источниках говорится, что PlayerPrefs нужно использовать очень осторожно и при каждом возможном случае вместо этого самостоятельно сериализовывать данные и писать их в собственные файлы. Раньше я старательно готовил свой формат бинарного файла для каждой сохраняемой сущности. Теперь я так не делаю.
Класс PlayerPrefs занимается тем, что хранит пары «ключ => значение» в файловой системе, причём работает одинаково на всех платформах, просто хранит свои файлы в разных местах.
Постоянно писать данные в поля PlayerPrefs (и читать их) — плохо: регулярные запросы к диску никому добра не делают. Однако можно написать простую, но разумную систему, которая поможет этого избежать.
Например, можно создать единый SAVE-объект, который хранит в себе все настройки и данные игрока:
Следите за объектами в сцене
Вот вы запустили свою игру. Она работает, вы радуетесь. Поиграли в неё минут 15, поставили на паузу, чтобы проверить этот любопытный ворнинг в консоли… ОБОЖЕМОЙ, ПОЧЕМУ У МЕНЯ В СЦЕНЕ 745 ОБЪЕКТОВ В КОРНЕ. КАК МНЕ ЧТО-НИБУДЬ НАЙТИ.
Избегайте GameObject.Find()
Очень дорогая с точки зрения ресурсов функция для поиска объектов. Да ещё и завязана она на имени объекта, которое нужно каждый раз изменять как минимум в двух местах (в сцене и в коде). То же можно сказать и про GameObject.FindWithTag() (я бы вообще предложил отказаться от использования тегов — всегда можно найти более удобные способы определения типа объекта).
Если уж очень приспичит, обязательно кешируйте в переменную каждый вызов, чтобы не делать его больше одного раза. Или вообще сделайте связи объектов через инспектор.
Важно: в отличие от большинства других функций для поиска объектов, transform.Find() возвращает даже отключенные (gameObject.active == false) в данный момент объекты.
Договоритесь с художником о формате изображений
Особенно если художник — это вы сами. Особенно если художник никогда раньше не работал над играми и IT-проектами в целом.
Дать много советов по текстурам для 3D-игр я не смогу — сам ещё глубоко в это не закапывался. Важно научить художника сохранять все картинки с POT-габаритами (Power Of Two, чтобы каждая сторона картинки была степенью двойки, например, 512х512 или 1024х2048), чтобы они эффективнее сжимались движком и не занимали драгоценные мегабайты (что особенно важно для мобильных игр).
А вот рассказать грустных историй про спрайты для 2D-игр я могу много.
Устанавливайте майлстоуны
Что это такое? По хорошему, майлстоун (milestones — камни, которые в былые времена устанавливали вдоль дороги каждую милю для отмечания расстояний) — это определённое состояние проекта, когда он достиг поставленных на данный момент целей и может переходить к дальнейшему развитию. А может и не переходить.
Наверное, это была наша главная ошибка при работе над дебютным проектом. Мы поставили перед собой очень много целей и шли ко всем сразу. Всегда что-то оставалось недоделанным, и мы никак не могли сказать: “А вот теперь проект действительно готов!”, потому что к имеющемуся функционалу постоянно хотелось добавить что-то ещё.
Не надо так делать. Лучший способ развития игры — точно знать конечный набор фич и не отходить от него. Но это уж больно редко бывает, если речь идёт не о крупной индустриальной разработке. Игры часто развиваются и модернизируются прямо в процессе разработки. Так как же вовремя остановиться?
Составьте план версий (майлстоунов). Так, чтобы каждая версия была завершённой игрой: чтобы не было никаких временных заглушек, костылей и недореализованного функционала. Так, чтобы на любом майлстоуне было не стыдно сказать: “На этом мы и закончим!” и выпустить в свет (или навсегда закрыть в шкафу) качественный продукт.
Заключение
Глупый я был три года назад, да? Надеюсь, вы не будете повторять мои ошибки и сэкономите много времени и нервов. А если вы боялись даже попробовать начать заниматься разработкой игр, может быть, я смог вас хоть немного на это мотивировать.
P. S. Я подумываю о написании туториала вида “Делаем игрушку для хакатона за сутки с нуля”, по которому человек без знания Unity и навыков программирования смог бы написать свою первую игру. На русском языке качественных туториалов такого формата не очень много. Как думаете, стоит попробовать?