Pull to refresh

Comments 32

Не совсем понял, зачем поворачивать весь уровень?
Можно ведь на самом деле двигать игрока и камеру вместе с ним.
А про физику, Transform и производительность — спасибо, этот момент обычно как-то замалчивается.
В статье про это написано. Игра бесконечна и координаты объектов, в определенный момент, могут начать обрубаться из-за того, что хранятся в float, что приведет к ужасающим багам. Как вариант — можно периодически телепортировать игрока обратно в (0;0;0), но это, опять же, приводит к лагам, в статье про это тоже написано :)
Если я правильно понял, предлагается уровень только двигать, а игрока и камеру только вращать.
Да, можно, как вариант. Почему-то не додумался до такого, спасибо. Возможно, так будет даже производительнее, возможно — нет, уже не имею профайлера, чтобы сравнить.
Но не суть важно, как это сделано конкретно в нашей игре, она в статье использована лишь как пример соблюдения и осознанного несоблюдения основных законов. И полное вращение уровня — хорошая демонстрация гибкости физики в Unity на низком уровне.
UFO just landed and posted this here
С движением вперед и прыжком все правильно, а вот повороты нужно делать, временно отклоняя вектор скорости.
UFO just landed and posted this here
Я бы сделал повороты изменением вектора скорости. Но можно придумать много других вариантов, это зависит от того, как вы себе представляете повороты в вашей игре. Идеального общего решения нет.
Для этих целей гораздо лучше подойдет CharachterController с его методом Move()
Пока есть только рабочее название, мы еще не релизились. Сейчас ищем издателя.
Хинты про производительность были особенны полезны.
Это как-раз тот опыт который экономит время.
Спасибо :)
Я верно понял, что все актёры сцены должны генерироваться «в чулане» (далеко от сцены) сразу при загрузке уровня и телепортироваться на нужное место уровня во время игры по мере надобности?
Да, автор рекомендует использовать фабрику, или точнее пул объектов (Pool Objects).
Да. Даже не обязательно далеко от сцены, объекты могут находиться выключенными (gameObject.SetActive(false)) и не потреблять ресурсов где угодно.
Я вот тоже делаю свой первый endless runner (не на Unity) и разбираюсь с такими же вопросами. Тоже изначально сделал движение уровня относительно игрока, но вижу, что производительности не хватает даже на моем Nexus 5. Теперь переделываю на движение игрока (и камеры вместе с ним) по генерируемым перед камерой участкам уровня. То есть, случайным образом, берется один из вариантов бэкграунда (которые бесшовно в друг друга переходят), на нем, опять же случайно, расставляются препятствия, а после прохождения игрока сегмент очищается и возвращается в пул для повторного использования. Думаю, размерность float значительно больше расстояния, которое игрок будет способен пройти даже для самой длинной игровой сессии. Ну а после рестарта уровня, телепортируемся в ноль-ноль, понятно.
Если правильно и со знанием законов сделать — тормозить не будет, 100%. А вот про float — не факт, есть корейцы и роботы… в остальном подход правильный.
Кинематические тела следуют упрощенным правилам симуляции — на них не воздействуют никакие внешние силы, гравитация — в том числе. Они свободно могут проходить через что угодно.

Кинематические тела не должны свободно проходить через что угодно. По крайней мере, все именно так в Box2D, который используется в Unity. Возможно, вы что-то напутали в настройках слоев?
Да, спасибо, неправильно выразился, сейчас исправлю. Они проходят через друг-друга и обычные коллайдеры, не-кинематические твердые тела они будут расталкивать.
Если использовать isKinematic то можно смело обращаться к transform и не будет необходимости работать через Rigidbody.
Если вы используете физические расчеты перемещения то применяйте силы в FixedUpdate, а не в Update.
Надеюсь, Unity не сильно обидится на меня за еще один триал…
Можно, да, но с падением производительности, где-то в два раза. Таков третий закон. Точно такая же картина с не-кинематическими телами.
Тест на 20 box-коллайдеров (больше лень было создавать). Слева — движение через rigidbody2d.MovePosition, справа — движение через transform.position.



Использованный для теста код
void FixedUpdate() {
    float v = Mathf.Sin( Time.timeSinceLevelLoad );
    Vector3 newPosition = stockPos + new Vector3( v, v );

    if( byTransform ) {
        cachedTransform.position = newPosition;
    } else {
        cachedRigidbody.MovePosition( newPosition );
    }
}
Что забавно — в 3D-физике, аналогичный код через transform работает быстрее. Разные движки, разные особенности…
слишком сложно, для такой простой игры…
Все игры кажутся простыми, если ты их не делал :(
Ну и это все же обучающая статья, если разработчик переживет эти проблемы — дальше ему будет проще.
Я вполне адекватно представляю как ее сделать. Я не считаю себя мега крутым разработчиком, но кое что из своей жизни я понял. Чем проще, тем лучше. Я не спорю, всегда что то кажется проще, пока ты не делал, это наш оптимизм ;)
Но я имел введу, что я бы сделал совсем по другому, и многие вопросы для меня просто не появились бы во время разработки :)
Тем не менее! Я рад что Вы поделились своим опытом с хабра-сообществом, я вот почему то не осилил и даже не думаю что это будет кому то интересно.
Само собой. Просто если не знать особенностей инструментария — иногда простые решения могут не работать, или работать неожиданно медленно :)
Как бы вы сделали, если не секрет? С учетом обхода очевидных проблем, описанных в статье, конечно же.
Для начала, я бы не использовал юнити, это лишнее обременение. Cocos2d-x тут бы хватило за глаза. Группировал рендер в батчи и двигал бы мир(он генерируемый, а значит ему существовать целиком не обязательно), вернее пулы кусочков мира. Использовал бы Box2D или нет, сложный вопрос, скорее нет, чем да. Мобильные платформы обременяют на размерность текстур и как мы помним переключение текстур до сих пор тяжелая операция. Поэтому максимум атласов текстурных. Могу с уверенностью сказать что даже самый галимый девайс на андройде весело срендерит батчинг на одной текстуру 1024х1024 нежели несколько 64х64, постоянно переключаясь.

Если вам интересно то можете найти в эпсторе (плей маркет) игру Выкрутасы. Хоть я там давно и не работаю, а мое имя в создателях потерли после обновления графики(да и кода наверно), я свой код все равно узнаю. Так вот, из за технических ограничений мне пришлось прокидывать видео с камеры через память озу. Это довольно дорогая операция, но я постарался максимально оптимизировать. Эта игра может показаться проще вашей, но как вы говорите «если ты их не делал» ;) хотя ничего сложного, там действительно нет. Больше грабли и сложности связанные с не нативной разработкой и желанием записывать видео игры. (особенно интересно было объединение видео и текста, у меня осталось время даже для этого)
А можно вопросик по поводу gameObject.SetActive? Имеется пул. Что будет лучше(и быстрее), перемещать объект в Infinity координаты и отключать только пользовательские компоненты или делать gameObject.SetActive? Объект имеет сложную иерархию.

Недавно товарищ столкнулся с тем, что имея на объекте Animator при SetActive терял очень много времени именно на нем. Хотя в том же официальном примере object-pool-а используется SetActive.
Мы используем SetActive и проблем с ним не было. Иерархия блоков и врагов тоже сложная бывает, скриптов куча, отключать каждый компонент — не вариант.
Аниматоры еще весьма прожорливы в режиме ожидания (значит, лучше их все же отключать) и действительно долго инициализируются. Но я с ними плотно не работал и не могу с уверенностью дать совет. Возможно, стоит их создавать активными, давать им возможность проинициализироваться, а потом выключать?
У нас в игре аниматор только один на весь UI, все мелкие движения на скриптах.
В документации написано, что если на обьекте есть коллайдер и его нужно двигать, то на нем обязан быть RigidBody — иначе будет серьезное падение в производительности.
Скорее всего это у вас и было — проверьте профайлером коллайдеры еще раз, но сначала на обьект повесьте RigidBody (Иначе получается глупо — зачем нужны коллайдеры, если обьекты нельзя двигать?)
Да, это у нас и было, и статья именно про это :)
Разве? Прочитав пункт номер 1: Коллайдеры не должны двигаться, вращаться, включаться\выключаться и менять размер. я понял что если на обьекте висит коллайдер, то всё — двигать его уже нельзя :)
Sign up to leave a comment.

Articles