Единство: Вычислите угловую скорость твердого тела, чтобы всегда смотреть в определенном направлении

#unity3d #physics #velocity

Вопрос:

Я пытаюсь сделать механика подбора предметов, как в Амнезии. Легко рассчитать необходимую скорость твердого тела, чтобы удерживаемый объект оставался перед камерой, но моя проблема в том, что объект вообще не вращается, когда я его держу. И я бы предпочел, чтобы он всегда был повернут в сторону камеры. Этого можно легко достичь, просто поместив объект в камеру игрока, но…

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

Я думаю, что для этого мне нужно рассчитать угловую скорость, и, вероятно, у меня есть немного lerp, чтобы вернуться к исходному вращению, но я не знаю, как это правильно сделать.

Я думаю, что первое, что мне нужно будет сделать, это сохранить начальное направление в тот момент, когда игрок поднимет объект:

 Vector3 targetDirection = playerCamera.transform.position - transform.position;
 

Скрипт находится на удерживаемом объекте, поэтому «преобразование» относится к нему. В FixedUpdate() мне, вероятно, потребуется некоторая интерполяция, чтобы угловая скорость всегда пыталась повернуть объект к исходному вращению:

 rigidbody.angularVelocity = Vector3.Lerp(rigidbody.angularVelocity, targetAngularVelocity, lerpSpeed * Time.fixedDeltaTime);
 

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

Комментарии:

1. Является ли простое использование rigidbody.MoveRotation не вариантом?

2. Как я уже сказал, возможно, для этого мне не нужно вычислять угловую скорость. Я мог бы использовать MoveRotation(), но все же я не уверен, как кодировать поведение, которое я описал.

Ответ №1:

Тебе нужен стабилизатор. Сценарий, который добавит крутящий момент/угловую скорость объекту, угол наклона которого отличается от целевого. Скажем, у вас есть две переменные: targetDirection и currentDirection ака transform.forward . Затем вы пишете что-то вроде этого в исправленном обновлении:

 var rotation = Quaternion.FromToRotation(currentDirection, targetDirection).eulerAngles * sensitivity;
rigidbody.angularVelocity = rotation;
 

Я рекомендую установить чувствительность около 0,05, а затем увеличить ее, если объект стабилизируется слишком медленно.
Вероятно, я перепутал порядок, поэтому вам следует где-то поставить минус, но сам подход применим.

Комментарии:

1. Спасибо! Но я думаю, что это должно быть что-то другое, чем Vector3.SignedAngle (), поскольку он возвращает float, а angularVelocity-это Vector3. Возможно, вы имели в виду Vector3.Lerp()?

2. О, я отредактировал ответ

3. Похоже, мы все еще чего-то не понимаем. С Кватернионом. FromToRotation() удерживаемый объект просто постоянно вращается, никогда не достигая своего первоначального вращения. Я попытался поместить разные вещи в текущее и целевое направление, например transform.forward или (PlayerCam.transform.position — преобразование.позиция), но, похоже, ничего не работает должным образом.

4. Вы имеете в виду rotation вместо angle этого ?

5. Ах, да. Я просто переименовал переменную, чтобы соответствовать ее значению)