使用 MRTK 交互时设置螺旋运动
Setup an helical movement when interacting using the MRTK
我正在尝试通过 min/max 限制实现螺旋运动:
- 正旋转 > 负变换
- 负旋转 > 正变换
正向和反向旋转都将通过 MRTK 手部交互提供的脚本完成,所以这不是我的问题。
我(认为)我在逻辑上挣扎。
tl;dr:我想用 Unity、MRTK 和虚拟手搞砸。
经过几天非常非常努力的摸索,我终于解决了我的问题。
老实说,我一个人可能不会成功,因为逻辑问题(这种情况经常发生,不是吗?)。
初始设置
在我的例子中,要与之交互的游戏对象是一颗螺丝钉。
我希望它在发生正向旋转时执行正向平移,反之亦然。
在这个游戏对象上附加了一些组件:
- 碰撞器(网格、盒子、胶囊)
- 刚体
- 一个PointerHandler.cs(捷运)
- a ObjectManipulator.cs (MRTK)
- a NearInteractionGrabbable.cs(捷运)
- 下面找到TwistingRotation.cs
刚体、PointerHandler.cs、ObjectManipulator.cs 和 TwistingRotation.cs 配置可以在这里找到:
魔法随 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(单位)单位平移上完成旋转。
结果
它远非完美,可能非常完美 "meh" 但是嘿,它正在工作(虽然不是预期的那样,但仍然如此)并且它让我继续前进并进行了演示。
我正在尝试通过 min/max 限制实现螺旋运动:
- 正旋转 > 负变换
- 负旋转 > 正变换
正向和反向旋转都将通过 MRTK 手部交互提供的脚本完成,所以这不是我的问题。 我(认为)我在逻辑上挣扎。
tl;dr:我想用 Unity、MRTK 和虚拟手搞砸。
经过几天非常非常努力的摸索,我终于解决了我的问题。 老实说,我一个人可能不会成功,因为逻辑问题(这种情况经常发生,不是吗?)。
初始设置
在我的例子中,要与之交互的游戏对象是一颗螺丝钉。 我希望它在发生正向旋转时执行正向平移,反之亦然。 在这个游戏对象上附加了一些组件:
- 碰撞器(网格、盒子、胶囊)
- 刚体
- 一个PointerHandler.cs(捷运)
- a ObjectManipulator.cs (MRTK)
- a NearInteractionGrabbable.cs(捷运)
- 下面找到TwistingRotation.cs
刚体、PointerHandler.cs、ObjectManipulator.cs 和 TwistingRotation.cs 配置可以在这里找到:
魔法随 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(单位)单位平移上完成旋转。
结果
它远非完美,可能非常完美 "meh" 但是嘿,它正在工作(虽然不是预期的那样,但仍然如此)并且它让我继续前进并进行了演示。