Вторник, 27 Октября 2020, 08:58

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

[ Новые сообщения · Игроделы · Правила · Поиск ]
  • Страница 1 из 1
  • 1
Модератор форума: beril  
Форум игроделов » Движки для разработки игр и сложные системы разработки » Unity » Проблема с поворотами объекта при многократном вращении
Проблема с поворотами объекта при многократном вращении
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.

Более 10 лет опыта разработки на разных языках высокого уровня.
Отличные знания .NET, Unity.
Отличные знания TCP, UDP.
Наличие выпущенных коммерческих проектов (Верхние рейтинги в Google Play и App Store).
Платные и бесплатные консультации по любым темам геймдева - Л.С.
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, спасибо за наводку, буду разбиратся
Форум игроделов » Движки для разработки игр и сложные системы разработки » Unity » Проблема с поворотами объекта при многократном вращении
  • Страница 1 из 1
  • 1
Поиск:

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