Страница 1 из 1

Как плавно повернуть объект на определенный угол.

СообщениеДобавлено: 04 сен 2009, 20:16
Serge
Первое что приходит в голову, запомнить текущий угол, прибавить к нему угол поворота и в цикле вращения сравнивать текущий угол с искомым. Только вот кажется что это не оптимальное решение. Какие еще могут быть варианты?

Re: Как плавно повернуть объект на определенный угол.

СообщениеДобавлено: 04 сен 2009, 23:17
Neodrop
Vector3.Lerp()

Re: Как плавно повернуть объект на определенный угол.

СообщениеДобавлено: 05 сен 2009, 08:06
Serge
Спасибо за подсказку, но я все-же не могу понять, как линейная интерполяция может мне помочь повернуть объект. Плавное перемещение из точки в точку за определенное время – без проблем, но поворот у меня не получается :-? . Нужна еще подсказка :) .

Re: Как плавно повернуть объект на определенный угол.

СообщениеДобавлено: 05 сен 2009, 09:08
PavelCrow
Да вон в соседней ветке посмотри, с косяком рыб.. Там как раз есть строчка с плавным поворотом. Через кватернион.

Re: Как плавно повернуть объект на определенный угол.

СообщениеДобавлено: 05 сен 2009, 09:27
ffinder
например так считаем кватернионы
Код: Выделить всё
q0 as Quaternion = transform.rotation
transform.LookAt(hint.transform)
q1 as Quaternion = transform.rotation

и потом делаем сферическую интерполяцию (в цикле)
Код: Выделить всё
transform.rotation = Quaternion.Slerp(q0, q1, t)

Re: Как плавно повернуть объект на определенный угол.

СообщениеДобавлено: 05 сен 2009, 11:16
Neodrop
На офф. WIKI есть класс вспомогательный. Кажется MathFX называется. Там есть плавные переходы по алгоритмам Бизье (кажется я видел такое :-? ).

Re: Как плавно повернуть объект на определенный угол.

СообщениеДобавлено: 07 сен 2009, 08:33
Serge
Применил предложенную методику и в результате у меня получился вот такой скрипт:
Код: Выделить всё
var smooth = 5.0;
var tiltAngle = 90.0;
var pauseTime = 3.0;

private var tiltAroundX = 0.0;
private var target : Quaternion;
private var nextTime = 0.0;

function Update () {
   
   if (Time.time > nextTime) {
      nextTime = Time.time + pauseTime;
      tiltAroundX += tiltAngle;
      target = Quaternion.Euler (tiltAroundX, 0, 0);
   }   
   
   transform.rotation = Quaternion.Slerp(transform.rotation, target, Time.deltaTime * smooth);
   
}

Его нужно кинуть на тот объект, который собираемся вращать. Скорость вращения задается параметром «smooth» он взаимосвязан с параметром «pauseTime», чем медленнее вращаем, тем больше нужна пауза. Если пауза будет меньше чем время вращения, может вылететь с ошибкой.
Все красиво, кроме одного, плавного разворота как такового нет. Есть рывок на старте и плавное замедление на финише. Можно поэкспериментировать со скоростью вращения, чтоб лучше увидеть. При использовании интерполяции для перемещения такого не наблюдал, странно.

Вопрос, так и должно быть, или в коде есть ошибка?

Re: Как плавно повернуть объект на определенный угол.

СообщениеДобавлено: 07 сен 2009, 10:43
ffinder
Пауза это жестко, да.
В интерполяции есть параметр t, вот он должен изменяться плавно.
Например:
animTime - продолжительность анимации
startTime - время начала анимации
тогда:
t = (Time.time - startTime) / animTime

и всё будет плавно.

Re: Как плавно повернуть объект на определенный угол.

СообщениеДобавлено: 07 сен 2009, 11:21
Serge
ffinder: благодарю за ответ, но скажите пожалуйста, вы мой код смотрели? Запускали? Если вы внимательно посмотрите код, то увидите, что пауза используется для того, чтобы делать повороты объекта через определенный промежуток времени и в интерполяции никак не используется. А если запустите данный скрипт, что несложно сделать, то увидите о чем идет речь.

Кстати ваш код мне не понятен, чему равно время начала анимации (startTime) и в какой момент вы его высчитываете?

Re: Как плавно повернуть объект на определенный угол.

СообщениеДобавлено: 07 сен 2009, 12:37
ffinder
Serge писал(а):Кстати ваш код мне не понятен, чему равно время начала анимации (startTime) и в какой момент вы его высчитываете?

Капитан Очевидность подсказывает, что в переменной startTime запоминаем текущее время в момент начала анимации.

Re: Как плавно повернуть объект на определенный угол.

СообщениеДобавлено: 07 сен 2009, 13:13
Serge
Интересно получается текущее время (Time.time) – текущее время (startTime) и поделить на время анимации (animTime), что получится :) ? Не ребята не понимаю, может приведете рабочий пример кода :-? ?

Re: Как плавно повернуть объект на определенный угол.

СообщениеДобавлено: 07 сен 2009, 13:53
Zavhoz
вот что получается

Код: Выделить всё
using UnityEngine;
using System.Collections;

public class SoftRotation: MonoBehaviour {
   public bool isRotate;
   
   public float mainTime=5;      //время интерполяции
   public float elapsedTime;
   public float mainValue;
   public float minValue=0;       //стартовая позиция
   public float maxValue=180;  //конечная позиция

   void Start () {
      
   }
   
   // Update is called once per frame
   void Update ()
   {
      if (Input.GetKey("space"))
         isRotate = true;

      
      if (isRotate)
      {
         elapsedTime+=Time.deltaTime;
      
         float progression= elapsedTime/mainTime;
         if (progression>1.0f) progression=1.0f;
      
         mainValue=Hermite(minValue,maxValue,progression);

         if (elapsedTime>mainTime) isRotate=false;
         
      }
      transform.rotation =  Quaternion.Euler(0, mainValue, 0);
   }
      

    public static float Hermite(float start, float end, float value){
        return Mathf.Lerp(start, end, value * value * (3.0f - 2.0f * value));
    }
}


часть кода взял на официальном WIKI (саму интерполяцию), часть подглядел в исходниках виртулза ;) (из безьепрогресии)

Re: Как плавно повернуть объект на определенный угол.

СообщениеДобавлено: 10 сен 2009, 17:50
Serge
Всем спасибо за советы и подсказки. Особое спасибо Zavhoz-у. В результате всего у меня получился вот такой скрипт. Может кому и пригодится.
Код: Выделить всё
var sped = 1.0;
var pauseTime = 1.5;
var angleRot = 90;
var mObject : Transform;

private var spedPrivate = 0.0;
private var nextTime = 0.0;

function Update () {

   if (Time.time > nextTime) {      
      nextTime = Time.time + pauseTime;
      spedPrivate = 0.0;      
   }
   
   spedPrivate += sped * Time.deltaTime;
   mObject.localRotation = Quaternion.Euler(0, 0, Mathf.LerpAngle(0, angleRot, spedPrivate));
   
}

Re: Как плавно повернуть объект на определенный угол.

СообщениеДобавлено: 20 сен 2009, 11:08
Serge
В процессе появился еще один вопрос, т.к. он касается предыдущего то задаю его здесь. Задача: требуется в цикле, через определенный промежуток времени поворачивать определенный объект, в данном случае кубик, на определенный угол, в течении заданного времени. Частично я задачу решил, решение приводилось выше. В коде Mathf.LerpAngle(0, angleRot, spedPrivate) для получения интерполяции задается начальный угол (0) и конечный (angleRot). В процессе выяснилось, что начальный угол у разных объектов будет разный. Решил получать стартовый угол через startAngle = mObject.localRotation.eulerAngles и в итоге получил вот такой код:
Код: Выделить всё
var sped = 0.5;
var pauseTime = 2.5;
var startAngle :Vector3;
var angleRot :Vector3;
var mObject : Transform;

private var spedPrivate = 0.0;
private var nextTime = 0.0;
private var endAngle :Vector3;

function Start () {
   nextTime = Time.time + pauseTime;
   angleRot = Vector3(90, 0, 0);
}

function Update () {

   if (Time.time > nextTime) {      
      
      nextTime = Time.time + pauseTime;
      spedPrivate = 0.0;
      startAngle = mObject.localRotation.eulerAngles;
      endAngle = startAngle + angleRot;
      
   }
   
   spedPrivate += sped * Time.deltaTime;
   mObject.localRotation = Quaternion.Euler(Mathf.LerpAngle(startAngle.x, endAngle.x, spedPrivate), 0, 0);
   
}

Теперь о проблеме: в первом проходе куб поворачивается на 90, во втором на 180 а затем почему то на 0.
В инспекторе видно, что после первого прохода Rotation = x = 90 y = 0, z = 0, после второго x = -5,008956e-06, y = 180, z = 180, после третьего опять x = 90 y = 0, z = 0 и так бесконечно. Получается, что кубик делает два поворота и возвращается в 0.
Вот собственно хотелось бы, чтобы мне помогли понять, что я делаю не так?

Re: Как плавно повернуть объект на определенный угол.

СообщениеДобавлено: 09 сен 2020, 19:04
Sergeyskripnikov
Zavhoz писал(а):вот что получается


Синтаксис:
Используется csharp
using UnityEngine;
using System.Collections;

public class SoftRotation: MonoBehaviour {
        public bool isRotate;
       
        public float mainTime=5;      //время интерполяции
        public float elapsedTime;
        public float mainValue;
        public float minValue=0;       //стартовая позиция
        public float maxValue=180;  //конечная позиция

        void Start () {
               
        }
       
        // Update is called once per frame
        void Update ()
        {
                if (Input.GetKey("space"))
                        isRotate = true;

               
                if (isRotate)
                {
                        elapsedTime+=Time.deltaTime;
               
                        float progression= elapsedTime/mainTime;
                        if (progression>1.0f) progression=1.0f;
               
                        mainValue=Hermite(minValue,maxValue,progression);

                        if (elapsedTime>mainTime) isRotate=false;
                       
                }
                transform.rotation =  Quaternion.Euler(0, mainValue, 0);
        }
               

    public static float Hermite(float start, float end, float value){
        return Mathf.Lerp(start, end, value * value * (3.0f - 2.0f * value));
    }
}
 


часть кода взял на официальном WIKI (саму интерполяцию), часть подглядел в исходниках виртулза ;) (из безьепрогресии)


Тут идёт плавное ускорение и плавное замедление, как я могу модифицировать код, чтобы сначала была максимальная скорость и колесо постепенно останавливалось?