Понедельник, 23 Декабря 2024, 03:54

Приветствую Вас Гость

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Проблема с поворотами объекта при многократном вращении
urbemAngeliДата: Воскресенье, 14 Августа 2016, 13:56 | Сообщение # 1
частый гость
Сейчас нет на сайте
Всем привет!Пытаюсь осуществить вращение обьекта при нажатии кнопки по одной из оси(y или z). Камера всегда неподвижна, и суть поворота куба заключается в том, что не зависимо от его поворота относительно камеры, если нажать кнопки(стрелки) он должен поворачиваться строго на 90 град. в том направлении как на скрине. Здесь у меня возникло две проблемы:
Проблема 1: Если куб допустим повернуть по оси z на +90° а затем по оси y на 180° , то при последующих поворотах вокруг z, кнопки вверх и вниз меняются местами, чего мне не нужно. Пришел к выводу что проблемой данного явления является когда узнаю текущие углы и добавляю или отнимаю 90 град, может происходить конфликт углов(допустим был угол -90 и нужно для правильного поворота -180, а у меня получается -90 + 90 = 0) и поэтому поворачивается не в ту сторону. Пробовал кубу добавлять родителя и у него брать углы, но тогда куб вращался как хотел.
Проблема 2: Если повернуть куб вдоль оси z, то при последующих поворотах вверх или вниз, вращение происходит по оси x, хотя в transform куба во время вращения углы меняются по z.
Помогите разобраться с данными проблемали, а то у самого мыслей уже 0 осталось как это можно решить.
Сорри что все так запутано описано, ниже скину еще проект, может кому наглядно лучше посмотреть на все это дело.



Код
public class HandlerRotation : MonoBehaviour
{
    Quaternion target;
    bool nowRotate = false;
    //public Transform parent;

    public int speed = 80;
    int nowFrame = 0;

    void FixedUpdate()
    {
        if (Input.GetKeyDown(KeyCode.UpArrow))
        {
            if (nowRotate == false) // Проверка для предотвращения поворота по второй оси
            {
                target = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y, transform.rotation.eulerAngles.z + 90);
                nowRotate = true;
            }
        }

        if (Input.GetKeyDown(KeyCode.DownArrow))
        {
            if (nowRotate == false)
            {
                target = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y, transform.rotation.eulerAngles.z - 90);
                nowRotate = true;
            }
        }

        if (Input.GetKeyDown(KeyCode.LeftArrow))
        {
            if (nowRotate == false)
            {
                target = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y + 90, transform.rotation.eulerAngles.z);
                nowRotate = true;
            }
        }

        if (Input.GetKeyDown(KeyCode.RightArrow))
        {
            if (nowRotate == false)
            {
                target = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y - 90, transform.rotation.eulerAngles.z);
                nowRotate = true;
            }
        }

        if (nowRotate)
        {
            if (nowFrame < 57) // Проверка на окончание поворота
            {
                transform.rotation = Quaternion.RotateTowards(transform.rotation, target, Time.deltaTime * speed);
                nowFrame++;
            }
            else
            {
                nowRotate = false;
                nowFrame = 0;
            }
        }
    }

Ссылка на проект


Сообщение отредактировал urbemAngeli - Воскресенье, 14 Августа 2016, 14:06
Storm54Дата: Воскресенье, 14 Августа 2016, 17:10 | Сообщение # 2
постоянный участник
Сейчас нет на сайте
Советую прочитать про Gimbal lock.
LertmindДата: Воскресенье, 14 Августа 2016, 18:16 | Сообщение # 3
заслуженный участник
Сейчас нет на сайте
Вот код:
Код
using UnityEngine;
using System.Collections;

public class HandlerRotation : MonoBehaviour
{
    public float Speed = 80;

    bool nowRotate = false;
    float angle = 0;
    Vector3 vectorRotation;

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.UpArrow))
        {
            if (!nowRotate)
            {
                nowRotate = true;
                vectorRotation = Vector3.forward;
            }
        }

        if (Input.GetKeyDown(KeyCode.DownArrow))
        {
            if (!nowRotate)
            {
                nowRotate = true;
                vectorRotation = Vector3.back;
            }
        }

        if (Input.GetKeyDown(KeyCode.LeftArrow))
        {
            if (!nowRotate)
            {
                nowRotate = true;
                vectorRotation = Vector3.up;
            }
        }

        if (Input.GetKeyDown(KeyCode.RightArrow))
        {
            if (!nowRotate)
            {
                nowRotate = true;
                vectorRotation = Vector3.down;
            }
        }

        if (nowRotate)
        {
            if (angle < 90f)
            {
                angle += Time.deltaTime * Speed;
                transform.Rotate(vectorRotation * Time.deltaTime * Speed, Space.World);
            }
            else
            {
                angle = 0f;
                nowRotate = false;

                transform.eulerAngles = new Vector3(
                    Mathf.RoundToInt(transform.eulerAngles.x / 90f) * 90f,
                    Mathf.RoundToInt(transform.eulerAngles.y / 90f) * 90f,
                    Mathf.RoundToInt(transform.eulerAngles.z / 90f) * 90f);
            }
        }
    }
}


Получилось не очень красиво из-за округления, можно по-другому, но сейчас я сразу не соображу. Если нужен FixedUpdate(), то не забывай менять Time.deltaTime на Time.fixedDeltaTime. А про Gimbal lock есть статья на хабре: https://habrahabr.ru/post/183116/.

Добавлено (14 августа 2016, 18:16)
---------------------------------------------
Есть ещё одна простая техника, когда создаёшь пустых родителей, каждого для вращения по одной из осей. В твоём случае - два, для удобства можно ещё одного в корне, который будет без вращения.

urbemAngeliДата: Воскресенье, 14 Августа 2016, 23:15 | Сообщение # 4
частый гость
Сейчас нет на сайте
Lertmind, только сейчас добрался до Unity, ваш скрипт работает просто супер, так как я и задумывал. Огромное спасибо:) Техника с родителями не совсем понятна, если первый родидель вращать по одной из оси, то для второго родителя(внутренний) остальные 2 оси будут отличными от мировых, и очень сложно будет реализовать вращение в требуемом направлении.

Сообщение отредактировал urbemAngeli - Воскресенье, 14 Августа 2016, 23:21
LertmindДата: Понедельник, 15 Августа 2016, 02:55 | Сообщение # 5
заслуженный участник
Сейчас нет на сайте
urbemAngeli, можно изменять локальные углы Эйлера (Transform.localRotation). Есть книга Building a Game with Unity and Blender - Lee Zhi Eng - 2015, там на странице 156 это используется.
urbemAngeliДата: Понедельник, 15 Августа 2016, 08:13 | Сообщение # 6
частый гость
Сейчас нет на сайте
Lertmind, спасибо за наводку, буду разбиратся
  • Страница 1 из 1
  • 1
Поиск:

Все права сохранены. GcUp.ru © 2008-2024 Рейтинг