Как я могу использовать несколько перечислений (два перечисления) для управления двумя осями, объект будет вращаться одновременно? - PullRequest
1 голос
/ 06 июня 2019
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Rotate : MonoBehaviour
{
    public enum Axistorotate { Back, Down, Forward, Left, Right, Up, Zero };
    public Vector3[] vectorAxises = new Vector3[7];

    public Axistorotate[] myAxis;
    public float angle;
    public float speed;

    private bool stopRotation = true;

    // Start is called before the first frame update
    void Start()
    {
        vectorAxises[0] = Vector3.back;
        vectorAxises[1] = Vector3.down;
        vectorAxises[2] = Vector3.forward;
        vectorAxises[3] = Vector3.left;
        vectorAxises[4] = Vector3.right;
        vectorAxises[5] = Vector3.up;
        vectorAxises[6] = Vector3.zero;

        StartCoroutine(RotateObject());
    }

    public Vector3 GetAxis(Axistorotate axis)
    {
        return vectorAxises[(int)axis];
    }

    // Update is called once per frame
    void Update()
    {
        if(Input.GetKeyDown(KeyCode.S))
        {
            stopRotation = false;
        }

        if (Input.GetKeyDown(KeyCode.C) && stopRotation == false)
        {
            stopRotation = true;
            StartCoroutine(RotateObject());
        }
    }

    IEnumerator RotateObject()
    {
        while (stopRotation == true)
        {
            for (int i = 0; i < myAxis.Length; i++)
            {
                transform.Rotate(GetAxis(myAxis[i]), angle);
            }
            yield return new WaitForSeconds(speed);
        }
    }
}

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

Как я могу обновить массив vectorAxises в режиме реального времени, когда игра запущена, чтобы показать в Инспекторе текущее состояние оси, например: vectorAxises[0] -> 1, 0, -1 ..... vectorAxises[7] -> 0,-1, 0 Я хочу это, когда я 'меняя одно из перечислений, чтобы оно отображало его на vectorAxises.

Может быть, мне нужно создать еще один массив vectorAxises по одному для каждого перечисления?

И, возможно, при выполнении двух myAxis он меняет один и тот же угол, так что это не два перечисления, которые изменяют индивидуальностьось?

Ответы [ 2 ]

1 голос
/ 06 июня 2019

transform.Rotate имеет необязательный параметр

relativeTo
Определяет, вращать ли GameObject локально по отношению к GameObject или относительно сцены в мировом пространстве.

, который по умолчанию равен Space.Self.

Итак, ваш

transform.Rotate(GetAxis(myAxis[i]), angle);

всегда выполняется в локальной системе координат GameObject. Эта локальная система вращается вместе с GameObject, поэтому локальная ось transform.up, transform.forward и т. Д. Постоянно меняется.


Вместо этого заставьте его вращаться вокруг мировой оси

transform.Rotate(GetAxis(myAxis[i]), angle, Space.World);

Как я могу обновить массив vectorAxises в режиме реального времени, пока игра запущена, чтобы показать в Инспекторе текущее состояние оси

Это уже должно быть так. Или вы имеете в виду, что хотите увидеть текущее «выбранное» значение. Вы должны использовать отладку и точки останова для этого. Так как вы делаете

for (int i = 0; i < myAxis.Length; i++)
{
    transform.Rotate(GetAxis(myAxis[i]), angle);
}

без дальнейших действий yield return объект будет напрямую "прыгать" в новое вращение, и в инспекторе вы всегда будете видеть только последние GetAxis(myAxis[i]).

Если вы ищете плавное вращение, проверьте Ответ Дест слегка измененный, например, вы могли бы. пусть объект вращается в течение 1 секунды

while (stopRotation == true)
{
    // calculate the target rotation
    Quaternion rotationQuaternion = Quaternion.identity;
    for (int i = 0; i < myAxis.Length; i++)
    {
        rotationQuaternion *= Quaternion.AngleAxis(angle, GetAxis(myAxis[i]));
    }

    // before starting to rotate store initial and target rotation
    var initialRotation = transform.rotation;
    var targetRotation = initialRotation * rotationQuaternion;

    // could also get this from the Inspector e.g.
    var rotationDuration = 1;

    // Do a smooth rotation from the initial to target rotation
    // within the defined rotationDuration 
    var timePassed = 0f;
    do
    {
        // additionally ease-in and -out the rotation
        var lerpFactor = Mathf.SmoothStep(0, 1, timePassed / rotationDuration);
        transform.rotation = Quaternion.Slerp(initialRotation, targetRotation, lerpFactor);

        timePassed += Time.deltaTime;

        // let this state be rendered
        yield return null;
    } while(timePassed < rotationDuration);

    // if you still want the pause 
    yield return new WaitForSeconds(speed);
}

Просто из любопытства: зачем вообще здесь использовать enum? Не могли бы вы вместо этого напрямую пройтись по индексу vectorAxises и добавить только те записи, которые вы будете использовать?

1 голос
/ 06 июня 2019

Используйте кватернионы для нескольких вращений одновременно:

Quaternion rotationQuaternion = Quaternion.identity;
for (int i = 0; i < myAxis.Length; i++)
{
    rotationQuaternion *= Quaternion.AngleAxis(angle, GetAxis(myAxis[i]));
}
transform.rotation *= rotationQuaternion;

Это должно решить вашу проблему с неправильными вращениями

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...