Подсчет полного оборота с круговым приводом - PullRequest
0 голосов
/ 01 апреля 2019

В течение последнего дня я ломал голову над тем, как рассчитать полное вращение и подсчитать полное вращение объекта вдоль оси X, используя базовый круговой привод из SteamVR.

Я подумал, что простой 3d-куб с выключенной сеткой на пути вращения с кодом столкновения - это простой способ сделать это, но он даже не регистрирует обнаружение, когда объект попадает впомещенные кубы, и я знаю, что это не из-за моей глупости, а из-за переработанного кода из рабочей части проекта.

Ниже у меня есть небольшой фрагмент кода, который в основном обнаруживает, когда объект достиг концавращения, а затем увеличивает счет на единицу.

Моя главная проблема в том, что иногда ему удается тактировать более одного раза, и если вы можете найти правильное место, вы можете просто сохранить его там и оно ».Я буду продолжать добавлять счет до.Мне интересно, как я могу остановить его и увеличивать только на единицу, пока не будет сделан еще один полный оборот?

РЕДАКТИРОВАТЬ: чтобы быть более ясным в случае каких-либо путаницы, как только угол между 359 и 360Я хочу, чтобы он увеличивался один раз, в то время как в настоящее время, если вы получите угол наклона где-нибудь между 359-360, он продолжит добавлять единицу к числу оборотов, несмотря на то, что полное вращение не было сделано, поэтому я пытаюсь выяснить, какзаставить мой код увеличиваться только один раз, и как только он будет увеличиваться, когда он сбрасывает позицию в ноль, поэтому больше не может происходить увеличения.Это кривошипно-шатунный механизм в VR, вдоль оси X.

Любая помощь приветствуется, спасибо!

 float Test;

float RotationCount = 0;

// Start is called before the first frame update
void Start()
{
   //  Test = transform.localRotation.eulerAngles.x;


}

// Update is called once per frame
void Update()
{

    if (Test > 359 && Test < 360)
    {
        Debug.Log("Clocked");
        count();
    }
    else
    {
      //  Debug.Log("Nope");
    }


    if (Test == 0)
    {
        Debug.Log("Yes");
    }

    Test = transform.localRotation.eulerAngles.x;

}

void count()
{

    RotationCount++;

}

1 Ответ

0 голосов
/ 01 апреля 2019

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

хорошо в

if (Test > 359 && Test < 360)
{
    Debug.Log("Clocked");
    count();
}

что произойдет, если ваш угол, например, 359.5

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


Я бы предпочел сохранить последний поворот, сравнить его с текущим и добавить разницу в переменную. Затем, если переменная превышает 360, выполняется полное вращение. Поскольку я также не люблю что-либо вычислять с помощью Quaternion и eulerAngles, проще использовать методы, предоставленные Vector3.

Для локального поворота вокруг X (== transform.right) я бы использовал угол между текущим и последним transfrm.up вектором.

что-то вроде

public class RotationCheck : MonoBehaviour
{
    public int RotationCount;

    public float rotatedAroundX;

    public Vector3 lastUp;

    public UnityEvent On3TimesRotated;

    private void Awake()
    {
        rotatedAroundX = 0;

        // initialize
        lastUp = transform.up;
    }

    private void Update()
    {
        var rotationDifference = Vector3.SignedAngle(transform.up, lastUp, transform.right);

        rotatedAroundX += rotationDifference;

        if (rotatedAroundX >= 360.0f)
        {
            Debug.Log("One positive rotation done", this);

            RotationCount++;

            rotatedAroundX -= 360.0f;
        }
        else if (rotatedAroundX <= -360.0f)
        {
            Debug.Log("One negative rotation done", this);

            RotationCount--;

            rotatedAroundX += 360.0f;
        }

        // update last rotation
        lastUp = transform.up;


        // check for fire the event
        if (RotationCount >= 3)
        {
            On3TimesRotated?.Invoke();

            RotationCount = 0;
        }
    }
}

Вы можете использовать UnityEvent , чтобы получить то же самое, что Button использует для onClick, так что вы можете ссылаться на обратные вызовы там через инспектора.

enter image description here


НО если вас не волнуют одиночные повороты, а фактически только финальный RotationCount >= 3 Я бы на самом деле использовал

private void Update()
{
    var rotationDifference = Vector3.SignedAngle(transform.up, lastUp, transform.right);

    rotatedAroundX += rotationDifference;

    RotationCount = Mathf.RoundToInt(rotatedAroundX / 360.0f);

    // update last rotation
    lastUp = transform.up;


    // check for fire the event
    if (RotationCount >= 3)
    {
        On3TimesRotated?.Invoke();

        RotationCount = 0;
        rotatedAroundX = 0;
    }
}

, который непосредственно уменьшает значение на единицу при повороте под отметкой 360 вместо ожидания полного отрицательного вращения

enter image description here

*, как вы можете видеть, вместо достижения 3, RotationCount сбрасывается в 0. Это то место, где событие On3TimesRotated запускается / запускается.

...