Комментарии 17
В корпоративном блоге Microsoft без ката…
if (direction == -1) transform.localScale = new Vector3 (-1, 1, 1); else transform.localScale = new Vector3 (1, 1, 1);
к чему лишние проверки?
transform.localScale = new Vector3 (direction, 1, 1);
Еще один момент. Этот код:
Сделает вращение зависимым от FPS.
Вот так лучше (теперь speed это градусы\секунда, а не градусы\update):
Особенно это важно для физики, а не для анимации. Но там используется фиксированный шаг (Time.fixedDeltaTime), очевидно, что ускорение игрока от фпс зависеть не должно :)
void Update () {
transform.Rotate (new Vector3 (0f, 0f, speed));
}
Сделает вращение зависимым от FPS.
Вот так лучше (теперь speed это градусы\секунда, а не градусы\update):
void Update () {
transform.Rotate (new Vector3 (0f, 0f, speed * Time.deltaTime));
// или
// transform.Rotate (Vector3.forward * speed * Time.deltaTime);
}
Особенно это важно для физики, а не для анимации. Но там используется фиксированный шаг (Time.fixedDeltaTime), очевидно, что ускорение игрока от фпс зависеть не должно :)
Ни в коем случае нельзя вращать или перемещать коллайдеры без твердых тел. Это вызывает их пересоздание и полный пересчет всей физики в кадре. Также, нельзя перемещать твердые тела через их трансформы. Вы можете этого не заметить на одной пиле, но уже пару сотен поставят любое мобильное устройство на колени. Добавьте на пилу kinematic твердое тело, отключите ему гравитацию и исправьте скрипт:
Без профайлера причина будущих тормозов будет совсем неочевидна. Тест на 240 пилах. Слева — ваша реализация. Посередине — пила с твердым телом, но вращение через трансформ. Справа — моя реализация.
В данном конкретном случае есть еще более быстрая альтернатива — делаете статический объект пилы, с коллайдером, но без спрайта, добавляете ему в детей еще один объект, но со спрайтом и вращаете именно его. Но можно забыть, что тело нельзя двигать, добавить какие-то движущиеся вращающиеся пилы и напороться на ту же ошибку…
Единственный допустимый вариант вращения объекта с коллайдером
public class Saw : MonoBehaviour
{
[SerializeField]
private float speed = 1f;
private float currentAngle = 0;
private Rigidbody2D cachedRigidbody;
void Awake() {
cachedRigidbody = rigidbody2D;
}
void Update() {
currentAngle += speed * Time.deltaTime;
currentAngle %= 360;
cachedRigidbody.MoveRotation( currentAngle );
}
}
Без профайлера причина будущих тормозов будет совсем неочевидна. Тест на 240 пилах. Слева — ваша реализация. Посередине — пила с твердым телом, но вращение через трансформ. Справа — моя реализация.
Многократная разница в производительности
В данном конкретном случае есть еще более быстрая альтернатива — делаете статический объект пилы, с коллайдером, но без спрайта, добавляете ему в детей еще один объект, но со спрайтом и вращаете именно его. Но можно забыть, что тело нельзя двигать, добавить какие-то движущиеся вращающиеся пилы и напороться на ту же ошибку…
Красивые графики, без комментариев заберу в копилку (если когда-нибудь доберусь до Unity).
Не подскажете, зачем сериализовать поле speed?
Не подскажете, зачем сериализовать поле speed?
[SerializeField] private float speed = 1f;
Кстати, может подскажете:
Начал делать один прототип, есть 2d планеты и физ. объекты на них и в космосе.
Физические тела, попадающие в коллайдер-триггер этой планеты, начинают притягиваться и вращаться вокруг центра.
Проблема возникает с вращением. Вращаю объекты через MovePosition и МоveRotation. (изначально делал добавление тел в transform самой планеты, при попадании в коллайдер, и вращал саму планету. Скорость и угловая скорость при этом, судя по всему, не «поворачивается». Отказался от такого наследования).
Ощущение, что при вызове MovePosition или МоveRotation сбрасывается либо скорость объекта, либо применяемые силы (стоит раскомментировать эти строки, аddForce перестает адекватно работать).
(Прошу прощения, что заставляю ванговать, куски исходников смогу отправить только вечером)
Начал делать один прототип, есть 2d планеты и физ. объекты на них и в космосе.
Физические тела, попадающие в коллайдер-триггер этой планеты, начинают притягиваться и вращаться вокруг центра.
Проблема возникает с вращением. Вращаю объекты через MovePosition и МоveRotation. (изначально делал добавление тел в transform самой планеты, при попадании в коллайдер, и вращал саму планету. Скорость и угловая скорость при этом, судя по всему, не «поворачивается». Отказался от такого наследования).
Ощущение, что при вызове MovePosition или МоveRotation сбрасывается либо скорость объекта, либо применяемые силы (стоит раскомментировать эти строки, аddForce перестает адекватно работать).
(Прошу прощения, что заставляю ванговать, куски исходников смогу отправить только вечером)
Я так понимаю, и планеты, и объекты у вас — твердые тела, а не просто коллайдеры. Твердое тело не может быть ребенком твердого тела и при этом вести себя нормально — родитель будет «доминировать» непредсказуемым образом, поэтому у вас не работало наследование.
MovePosition и MoveRotation выполняют, по сути, физическую телепортацию за один кадр, что применимо лишь в очень простых или очень синтетических случаях, вроде вращения пилы или движения уровня вокруг игрока. Т.е. если ваши твердые тела кинематические и следуют упрощенным правилам симуляции. Скорость, сила, трение — более сложные понятия и при телепортации могут ломаться. Если вы планируете использовать MovePosition с MoveRotation и вам хочется иметь силы и скорости — вам придется написать с их использованием свой собственный addForce, addVelocity и.т.п., потому что имеющиеся могут вести себя непредсказуемо криво.
Если вам нужно просто начать красиво падать на планету при пролете мимо — добавляйте силу в направлении ее центра в OnTriggerStay2D — это будет лучшим решением. Если вам нужно выйти на орбиту и держаться на ней, при этом используя физический движок… все будет намного сложнее, придется достать школьных учебников по физике и это уже тема для отдельной статьи.
Думаю, на неделе напишу статью про свою борьбу с физикой в Unity… в нашей игре физика используется ну очень специфически и движок был явно не готов к таким конструкциям.
MovePosition и MoveRotation выполняют, по сути, физическую телепортацию за один кадр, что применимо лишь в очень простых или очень синтетических случаях, вроде вращения пилы или движения уровня вокруг игрока. Т.е. если ваши твердые тела кинематические и следуют упрощенным правилам симуляции. Скорость, сила, трение — более сложные понятия и при телепортации могут ломаться. Если вы планируете использовать MovePosition с MoveRotation и вам хочется иметь силы и скорости — вам придется написать с их использованием свой собственный addForce, addVelocity и.т.п., потому что имеющиеся могут вести себя непредсказуемо криво.
Если вам нужно просто начать красиво падать на планету при пролете мимо — добавляйте силу в направлении ее центра в OnTriggerStay2D — это будет лучшим решением. Если вам нужно выйти на орбиту и держаться на ней, при этом используя физический движок… все будет намного сложнее, придется достать школьных учебников по физике и это уже тема для отдельной статьи.
Думаю, на неделе напишу статью про свою борьбу с физикой в Unity… в нашей игре физика используется ну очень специфически и движок был явно не готов к таким конструкциям.
Потрясающе компактный и насыщенный полезностью комментарий. Вроде я так и не делал, но свой проект на всякий случай перепроверю :)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Про создание платформера на Unity. Часть 4.1, злодейская