Настройка винтового движения при взаимодействии с помощью MRTK - PullRequest
0 голосов
/ 02 апреля 2020

Я пытаюсь добиться спирального движения с минимальным / максимальным ограничением:

  • положительное вращение> отрицательное преобразование
  • отрицательное вращение> положительное преобразование

Как положительное, так и отрицательное вращение будет выполнено с помощью сценария взаимодействия рук MRTK, так что это не моя проблема. Я (думаю), что я борюсь с логикой c.

tl; dr: я хочу прикрутить что-нибудь, используя Unity, MRTK и виртуальные руки.

1 Ответ

0 голосов
/ 21 апреля 2020

Я закончил тем, что решил свою проблему, после нескольких дней чесания моей головы действительно, очень сильно. Если честно, я бы, наверное, не справился бы сам по себе из-за проблемы с logi c (это очень часто так, не так ли?).


Initial Setup

В моем случае игровой объект, с которым нужно взаимодействовать, представляет собой винт. Я хотел, чтобы он выполнял положительный перевод, когда происходит положительный поворот, и наоборот. К этому игровому объекту прикреплены некоторые компоненты:

  • коллайдер (мне sh, коробка, капсула)
  • твердое тело
  • PointerHandler.cs (MRTK)
  • a ObjectManipulator.cs (MRTK)
  • a NearInteractionGrabbable.cs (MRTK)
  • TwistingRotation.cs, найденный ниже

твердое тело, PointerHandler.cs, ObjectManipulator.cs и конфигурации TwistingRotation.cs можно найти здесь:

Components configuration

Волхвы c появляются вместе с PointerHandler.cs которые позволяют нам определять, когда происходит близкое взаимодействие с винтом, благодаря событию OnPointerDragged.


TwistingRotation.cs

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// Translation of the object while rotating it when grabbed using the MRTK.ObjectManipulator
/// Boundaries and axis restrictions ongoing
/// </summary>

public class TwistingRotation : MonoBehaviour
{
    /*******CACHE REFERENCE*******/
    private Transform _myTransform;

    [SerializeField] private float translationFactor = 90f;

    private Vector3 _minPosition;
    private Vector3 _maxPosition;
    private Vector3 _previousVector;
    private Rigidbody _rb;


    private void Start()
    {
        // Cache reference
        _myTransform = gameObject.transform;
        _rb = gameObject.GetComponent<Rigidbody>();

        // Reference for the previous rotation vector
        _previousVector = _myTransform.up;
        // Default position is the maximum transform.position (unscrewed)
        _maxPosition = _myTransform.position;
        // Minimum position is default transform.position + 1unit in local space direction
        _minPosition = _maxPosition + Vector3.forward;
    }

    /// <summary>
    /// Move the object according to the rotation angle value
    /// A positive rotation leads to a positive translation, and vice-versa
    /// </summary>
    public void TranslateRotation()
    {
        // Retrieve the angle on a defined local axis when the rotation occur
        var currentVector = _myTransform.up;
        // Compute the angle between the previous and the current vector on a defined local axis
        // Difference between the previous rotation vector, and the actual, on a global axis
        var angle = Vector3.SignedAngle(_previousVector, currentVector, Vector3.forward);

        // Move object proportional to its rotation
        var translation = Vector3.forward * (angle / translationFactor);
        _myTransform.Translate(translation, Space.Self);

        // Get the GO current position
        var currentPosition = _myTransform.position;
        // Clamp for each axis between _minPosition and _maxPosition (the default spawn position)
        // Doing a Mathf.Min/Max inside the Mathf.Clamp to insure that the min and max values are correct 
        var x = Mathf.Clamp(currentPosition.x, Mathf.Min(_minPosition.x, _maxPosition.x), Mathf.Max(_minPosition.x, _maxPosition.x));
        var y = Mathf.Clamp(currentPosition.y, Mathf.Min(_minPosition.y, _maxPosition.y), Mathf.Max(_minPosition.y, _maxPosition.y));
        var z = Mathf.Clamp(currentPosition.z, Mathf.Min(_minPosition.z, _maxPosition.z), Mathf.Max(_minPosition.z, _maxPosition.z));

        // Compute the new position while taking the boundaries into consideration
        var newPosition = new Vector3(x, y, z);
        _myTransform.position = newPosition;

        // Save position for the next frame
        _previousVector = currentVector;
    }
}

Что происходит?

Довольно просто: при вращении винт перемещается более чем на 1 (единицу). Значение поворота зависит от значения переменной translationFactor. В моем случае это значение 360, так что полный оборот за единицу перевода (1).


Результат

Это далеко не идеально, вероятно, очень "ме" но эй, это работает (не так, как задумано, но все же), и это позволило мне двигаться вперед, и я сделал свою презентацию.

Final result

...