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

Программирование на Юнити.

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

Сообщение Serge 04 сен 2009, 20:16

Первое что приходит в голову, запомнить текущий угол, прибавить к нему угол поворота и в цикле вращения сравнивать текущий угол с искомым. Только вот кажется что это не оптимальное решение. Какие еще могут быть варианты?
О, сколько нам открытий чудных Готовят просвещенья дух И опыт, сын ошибок трудных, И гений, парадоксов друг, И случай, бог изобретатель.
Аватара пользователя
Serge
UNIверсал
 
Сообщения: 476
Зарегистрирован: 20 мар 2009, 15:53
Откуда: Сибирь г. Омск
  • Сайт
  • ICQ

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

Сообщение Neodrop 04 сен 2009, 23:17

Vector3.Lerp()
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8480
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

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

Сообщение Serge 05 сен 2009, 08:06

Спасибо за подсказку, но я все-же не могу понять, как линейная интерполяция может мне помочь повернуть объект. Плавное перемещение из точки в точку за определенное время – без проблем, но поворот у меня не получается :-? . Нужна еще подсказка :) .
О, сколько нам открытий чудных Готовят просвещенья дух И опыт, сын ошибок трудных, И гений, парадоксов друг, И случай, бог изобретатель.
Аватара пользователя
Serge
UNIверсал
 
Сообщения: 476
Зарегистрирован: 20 мар 2009, 15:53
Откуда: Сибирь г. Омск
  • Сайт
  • ICQ

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

Сообщение PavelCrow 05 сен 2009, 09:08

Да вон в соседней ветке посмотри, с косяком рыб.. Там как раз есть строчка с плавным поворотом. Через кватернион.
PavelCrow
UNец
 
Сообщения: 25
Зарегистрирован: 21 май 2009, 10:10

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

Сообщение ffinder 05 сен 2009, 09:27

например так считаем кватернионы
Код: Выделить всё
q0 as Quaternion = transform.rotation
transform.LookAt(hint.transform)
q1 as Quaternion = transform.rotation

и потом делаем сферическую интерполяцию (в цикле)
Код: Выделить всё
transform.rotation = Quaternion.Slerp(q0, q1, t)
ffinder
UNITрон
 
Сообщения: 192
Зарегистрирован: 26 мар 2009, 17:35
  • Сайт

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

Сообщение Neodrop 05 сен 2009, 11:16

На офф. WIKI есть класс вспомогательный. Кажется MathFX называется. Там есть плавные переходы по алгоритмам Бизье (кажется я видел такое :-? ).
Добавить neodrop в Skype
Изображение
"Спасибо!" нашему порталу, вы сможете сказать ЗДЕСЬ.
Если проблема не решается честно, нужно её обмануть! || Per stupiditas at Astra!
Страх порождает слабость. Бесстрашных поражают пули.
Протратившись на блядях байтах, на битах не экономят.
Аватара пользователя
Neodrop
Админ
 
Сообщения: 8480
Зарегистрирован: 08 окт 2008, 15:42
Откуда: Питер
Skype: neodrop
  • Сайт

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

Сообщение Serge 07 сен 2009, 08:33

Применил предложенную методику и в результате у меня получился вот такой скрипт:
Код: Выделить всё
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», чем медленнее вращаем, тем больше нужна пауза. Если пауза будет меньше чем время вращения, может вылететь с ошибкой.
Все красиво, кроме одного, плавного разворота как такового нет. Есть рывок на старте и плавное замедление на финише. Можно поэкспериментировать со скоростью вращения, чтоб лучше увидеть. При использовании интерполяции для перемещения такого не наблюдал, странно.

Вопрос, так и должно быть, или в коде есть ошибка?
О, сколько нам открытий чудных Готовят просвещенья дух И опыт, сын ошибок трудных, И гений, парадоксов друг, И случай, бог изобретатель.
Аватара пользователя
Serge
UNIверсал
 
Сообщения: 476
Зарегистрирован: 20 мар 2009, 15:53
Откуда: Сибирь г. Омск
  • Сайт
  • ICQ

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

Сообщение ffinder 07 сен 2009, 10:43

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

и всё будет плавно.
ffinder
UNITрон
 
Сообщения: 192
Зарегистрирован: 26 мар 2009, 17:35
  • Сайт

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

Сообщение Serge 07 сен 2009, 11:21

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

Кстати ваш код мне не понятен, чему равно время начала анимации (startTime) и в какой момент вы его высчитываете?
О, сколько нам открытий чудных Готовят просвещенья дух И опыт, сын ошибок трудных, И гений, парадоксов друг, И случай, бог изобретатель.
Аватара пользователя
Serge
UNIверсал
 
Сообщения: 476
Зарегистрирован: 20 мар 2009, 15:53
Откуда: Сибирь г. Омск
  • Сайт
  • ICQ

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

Сообщение ffinder 07 сен 2009, 12:37

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

Капитан Очевидность подсказывает, что в переменной startTime запоминаем текущее время в момент начала анимации.
ffinder
UNITрон
 
Сообщения: 192
Зарегистрирован: 26 мар 2009, 17:35
  • Сайт

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

Сообщение Serge 07 сен 2009, 13:13

Интересно получается текущее время (Time.time) – текущее время (startTime) и поделить на время анимации (animTime), что получится :) ? Не ребята не понимаю, может приведете рабочий пример кода :-? ?
О, сколько нам открытий чудных Готовят просвещенья дух И опыт, сын ошибок трудных, И гений, парадоксов друг, И случай, бог изобретатель.
Аватара пользователя
Serge
UNIверсал
 
Сообщения: 476
Зарегистрирован: 20 мар 2009, 15:53
Откуда: Сибирь г. Омск
  • Сайт
  • ICQ

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

Сообщение Zavhoz 07 сен 2009, 13:53

вот что получается

Код: Выделить всё
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 (саму интерполяцию), часть подглядел в исходниках виртулза ;) (из безьепрогресии)
FUNNY BLOX
Аватара пользователя
Zavhoz
UNITрон
 
Сообщения: 197
Зарегистрирован: 10 фев 2009, 07:23
Откуда: Караганда KZ
  • ICQ

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

Сообщение Serge 10 сен 2009, 17:50

Всем спасибо за советы и подсказки. Особое спасибо 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));
   
}
О, сколько нам открытий чудных Готовят просвещенья дух И опыт, сын ошибок трудных, И гений, парадоксов друг, И случай, бог изобретатель.
Аватара пользователя
Serge
UNIверсал
 
Сообщения: 476
Зарегистрирован: 20 мар 2009, 15:53
Откуда: Сибирь г. Омск
  • Сайт
  • ICQ

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

Сообщение Serge 20 сен 2009, 11:08

В процессе появился еще один вопрос, т.к. он касается предыдущего то задаю его здесь. Задача: требуется в цикле, через определенный промежуток времени поворачивать определенный объект, в данном случае кубик, на определенный угол, в течении заданного времени. Частично я задачу решил, решение приводилось выше. В коде 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.
Вот собственно хотелось бы, чтобы мне помогли понять, что я делаю не так?
О, сколько нам открытий чудных Готовят просвещенья дух И опыт, сын ошибок трудных, И гений, парадоксов друг, И случай, бог изобретатель.
Аватара пользователя
Serge
UNIверсал
 
Сообщения: 476
Зарегистрирован: 20 мар 2009, 15:53
Откуда: Сибирь г. Омск
  • Сайт
  • ICQ

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

Сообщение Sergeyskripnikov 09 сен 2020, 19:04

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 (саму интерполяцию), часть подглядел в исходниках виртулза ;) (из безьепрогресии)


Тут идёт плавное ускорение и плавное замедление, как я могу модифицировать код, чтобы сначала была максимальная скорость и колесо постепенно останавливалось?
Аватара пользователя
Sergeyskripnikov
UNец
 
Сообщения: 10
Зарегистрирован: 10 фев 2020, 12:00
Откуда: Оренбург


Вернуться в Скрипты

Кто сейчас на конференции

Сейчас этот форум просматривают: GoGo.Ru [Bot] и гости: 6