Unity 3D - Вращение объекта по отношению к его скорости

В настоящее время я тестирую Unity 3D, и у меня возникла проблема. Проблема в том, что у меня есть автомобиль, который движется по дороге, а затем, когда он достигает угла, я бы хотел, чтобы он повернул за угол и вращался по своей текущей скорости.

Вот код для перемещения объекта вперед:

_velocity += (_velocity * Time.deltaTime) + (_acceleration / 2f) * Time.deltaTime * 2f;
_velocity = Mathf.Clamp(_velocity, 0f, MaxVelocity);
Vector3 position = this.transform.position;
position += -this.transform.forward * _velocity * Time.deltaTime;
this.transform.position = position;

Переменные объявляются как члены класса:

private const float MaxVelocity = 10;
private float _velocity;
private float _acceleration;

Кажется, что он работает нормально, чтобы двигаться вперед. Если я применил поворот, он может выглядеть нормально для определенной скорости, но если скорость изменится, то вращение кажется быстрым или медленным.

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

Я пробовал несколько вариантов, за бесчисленные часы, но мне не повезло!

Любые идеи?

ОБНОВЛЕНИЕ # 1 :

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

Из того, что я разработал, вращение LERP из текущего направления в новое направление сделало трюк (вид!). Итак, я создал поведение под названием VehicleController и в Awake Я добавил следующее:

_target = this.transform.rotation * Quaternion.Euler(0f, 90f, 0f);

Это дало мне вращение цели относительно моего текущего вращения, то есть мое вращение должно было бы равняться _target, чтобы я столкнулся желаемое направление. Затем я добавил следующее к методу FixedUpdate:

//  Rotate
if(_doTurn)
{
    this.transform.rotation = Quaternion.Lerp(this.transform.rotation, _target, Time.fixedDeltaTime * _velocity);
}

Это выполнило фактическое вращение. Ключевой частью была установка третьего параметра Time.fixedDeltaTime * _velocity. Это означало, что моя скорость вращения соответствовала моей скорости.

Мой последний метод FixedUpdate выглядел следующим образом:

//  Forward
_velocity += (_velocity * Time.deltaTime) + (_acceleration / 2f) * Time.fixedDeltaTime * 2f;
_velocity = Mathf.Clamp(_velocity, 0f, MaxVelocity);
Vector3 position = this.transform.position;
position += -this.transform.forward * _velocity * Time.fixedDeltaTime;
this.transform.position = position;

//  Rotate
if(_doTurn)
{
    this.transform.rotation = Quaternion.Lerp(this.transform.rotation, _target, Time.fixedDeltaTime * _velocity);
}

В этом примере у меня был BoxCollider, который вызвал поворот, поэтому в OnTriggerEnter Я просто установил _doTurn в true

Теперь есть несколько вещей с этим:

  1. После поворота мне пришлось немного поправить позиционирование и поворот. Значения были примерно на 0,2, но я не мог заметить каких-либо странностей, которые вам нужно.
  2. Этот подход дает быстрое мгновенное изменение направления, которое не было тем, чем я действительно был. В идеале мне нужна была ситуация, когда поворот был бы постепенным под определенным углом и заканчивался бы в той же точке. Но, честно говоря, все выглядит нормально, и теперь меня заставляет двигаться дальше! :)

Что касается №1, я думаю, что мне пришлось исправить некоторые значения позиции /вращения, потому что я использовал BoxCollider для запуска поворот, чтобы могли быть лучшие подходы.

3 голоса | спросил MotoSV 30 PMpThu, 30 Apr 2015 17:55:21 +030055Thursday 2015, 17:55:21

1 ответ


1

Самый простой способ поворота объекта в направлении его скорости - представлять вращение как вектор. Физика Юнити делает это внутренне, но, к сожалению, не позволит вам получить доступ к любой из этих переменных. Вместо этого вы можете просто применить Torque, который сделает все для вас (неплохо использовать физический движок и самостоятельно применять физику).

Сначала выберите нужный поворот.

Vector3 DesiredRotation = Quaternion.LookRotation(rigidbody.Velocity).EulerAngles;

Затем найдите вращение, необходимое для вращения:

Vector3 RotationSteering = DesiredRotation - rigidbody.rotation;

Normalize RotationSteering, чтобы вы могли получить больше контроля над степенью вращения:

RotationSteering.Normalize();

Умножьте рулевое управление на любую сумму, которую вы хотите повернуть.

RotationSteering *= 30;

Примените силу, затем $$$:

rigidbody.AddTorque (RotationSteering);

Я не уверен, как Unity обрабатывает Torque, но это физический путь. Если вы хотите полный контроль, вы можете установить вращение вручную, но это приводит к множеству неудобных вещей. Вам также придется изменить скорость вращения для реалистичных столкновений. Просто придерживайтесь стандартного (хотя и ошибочного) колеса и не изобретайте его. У вас будет гораздо меньше головных болей.

ответил JPtheK9 1 Mayam15 2015, 07:43:53

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132