我正在研究VR交互,希望能够旋转物体,但我遇到了问题。
例如,我想在VR中使用手打开/关闭笔记本电脑的上部。为了实现这一点,我将前置摆放如下:
我正在使用位置、前向和上方创建一个飞机。然后获取与我的VR控制器对应的平面上最接近的点,然后使用transform.LookAt。这个方法很好用,但我想能够限制旋转,以便不能旋转太多(请参见视频结尾)。我尝试了一切,使用eulersAngle和Quaternion,但我无法做到。我制作了一些助手(用于显示localEulerAngles的文本和LookAt的变换,因此我不必使用VR头戴式耳机,因为它变得非常乏味)。这里是一个视频展示了正在发生的事情: https://www.youtube.com/watch?v=UfN97OpYElk。这是我的代码:using UnityEngine;
public class JVRLookAtRotation : MonoBehaviour, IJVRControllerInteract
{
[SerializeField] private Transform toRotate;
[SerializeField] private Vector3 minRotation;
[SerializeField] private Vector3 maxRotation;
[Header("Rotation contraints")]
[SerializeField] private bool lockX;
[SerializeField] private bool lockY;
[SerializeField] private bool lockZ;
private JVRController _jvrController;
private bool _isGrabbed;
private Vector3 _targetPosition;
private Vector3 _tmp;
public Transform followTransform;
private void LateUpdate()
{
/*
if (!_isGrabbed) return;
if (_jvrController.Grip + _jvrController.Trigger < Rules.GrabbingThreshold)
{
_isGrabbed = false;
_jvrController.StopGrabbing();
_jvrController = null;
return;
}
*/
Vector3 up = toRotate.up;
Vector3 forward = toRotate.forward;
Vector3 pos0 = toRotate.position;
Vector3 pos1 = pos0 + up;
Vector3 pos2 = pos0 + forward;
Plane p = new Plane(pos0, pos1, pos2);
// Using followTransform just to no have to use VR, otherwise it's the controller pos
_targetPosition = p.ClosestPointOnPlane(followTransform.position);
toRotate.LookAt(_targetPosition, up);
/*
_tmp = toRotate.localEulerAngles;
_tmp.x = Mathf.Clamp(WrapAngle(_tmp.x), minRotation.x, maxRotation.x);
_tmp.y = WrapAngle(_tmp.y);
_tmp.z = WrapAngle(_tmp.z);
toRotate.localRotation = Quaternion.Euler(_tmp);
*/
}
public void JVRControllerInteract(JVRController jvrController)
{
if (_isGrabbed) return;
if (!(jvrController.Grip + jvrController.Trigger > Rules.GrabbingThreshold)) return;
_jvrController = jvrController;
_jvrController.SetGrabbedObject(this);
_isGrabbed = true;
}
private static float WrapAngle(float angle)
{
angle%=360;
if(angle >180)
return angle - 360;
return angle;
}
private static float UnwrapAngle(float angle)
{
if(angle >=0)
return angle;
angle = -angle%360;
return 360-angle;
}
}