Как стать автором
Обновить

Комментарии 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);
И правда! Спасибо, добавлю в пост!
A вдруг direction нуль иль абы что. Будет весело вдоль x.
Как инструкция
direction *= -1;

может превратить '1' в «нуль иль абы что»?
Да легко, Вы же ошиблись при копировании инструкции)
Еще один момент. Этот код:
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), очевидно, что ускорение игрока от фпс зависеть не должно :)
По-моему, такое замечание было в комментариях к одному из прошлых постов. Вечно забываю про Time.deltaTime! Спасибо большое!
Ни в коем случае нельзя вращать или перемещать коллайдеры без твердых тел. Это вызывает их пересоздание и полный пересчет всей физики в кадре. Также, нельзя перемещать твердые тела через их трансформы. Вы можете этого не заметить на одной пиле, но уже пару сотен поставят любое мобильное устройство на колени. Добавьте на пилу kinematic твердое тело, отключите ему гравитацию и исправьте скрипт:
Единственный допустимый вариант вращения объекта с коллайдером
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?
[SerializeField]
    private float speed = 1f;
Таким образом оно остается private и сохраняется инкапсуляция, но при этом остается возможность удобного изменения его значения непосредственно в редакторе.
Грубо говоря, это пометка «показывать в редакторе».
Кстати, может подскажете:
Начал делать один прототип, есть 2d планеты и физ. объекты на них и в космосе.
Физические тела, попадающие в коллайдер-триггер этой планеты, начинают притягиваться и вращаться вокруг центра.
Проблема возникает с вращением. Вращаю объекты через MovePosition и МоveRotation. (изначально делал добавление тел в transform самой планеты, при попадании в коллайдер, и вращал саму планету. Скорость и угловая скорость при этом, судя по всему, не «поворачивается». Отказался от такого наследования).
Ощущение, что при вызове MovePosition или МоveRotation сбрасывается либо скорость объекта, либо применяемые силы (стоит раскомментировать эти строки, аddForce перестает адекватно работать).

(Прошу прощения, что заставляю ванговать, куски исходников смогу отправить только вечером)
Я так понимаю, и планеты, и объекты у вас — твердые тела, а не просто коллайдеры. Твердое тело не может быть ребенком твердого тела и при этом вести себя нормально — родитель будет «доминировать» непредсказуемым образом, поэтому у вас не работало наследование.
MovePosition и MoveRotation выполняют, по сути, физическую телепортацию за один кадр, что применимо лишь в очень простых или очень синтетических случаях, вроде вращения пилы или движения уровня вокруг игрока. Т.е. если ваши твердые тела кинематические и следуют упрощенным правилам симуляции. Скорость, сила, трение — более сложные понятия и при телепортации могут ломаться. Если вы планируете использовать MovePosition с MoveRotation и вам хочется иметь силы и скорости — вам придется написать с их использованием свой собственный addForce, addVelocity и.т.п., потому что имеющиеся могут вести себя непредсказуемо криво.
Если вам нужно просто начать красиво падать на планету при пролете мимо — добавляйте силу в направлении ее центра в OnTriggerStay2D — это будет лучшим решением. Если вам нужно выйти на орбиту и держаться на ней, при этом используя физический движок… все будет намного сложнее, придется достать школьных учебников по физике и это уже тема для отдельной статьи.
Думаю, на неделе напишу статью про свою борьбу с физикой в Unity… в нашей игре физика используется ну очень специфически и движок был явно не готов к таким конструкциям.
Нет, сама планета — не твердая, это некая зона, отображаемая графически:
Выглядит это так
image

На нее повешан триггер, в обработчике OnTriggerStay2D которого я применяю гравитацию, вращение и т.д.
И после применения в нем MovePosition и MoveRotation, похоже, применяемые силы и правда ломаются.
Потрясающе компактный и насыщенный полезностью комментарий. Вроде я так и не делал, но свой проект на всякий случай перепроверю :)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий