【发布时间】:2020-04-11 01:14:48
【问题描述】:
仍在研究 VR 交互,我希望能够旋转对象,但我遇到了问题。
例如,我想在 VR 中用手打开/关闭笔记本电脑的上部。我正在做的是实现这一点,就是这样放置前锋:
我正在使用 position, forward, up 创建一个平面。然后获取平面上与我的 VR 控制器对应的最近点,然后使用 transform.LookAt。
这工作正常,但我希望能够限制旋转,所以我不能旋转太多(见视频结尾)。
我一直在尝试一切,使用 eulersAngle 和四元数,但我无法做到。
我制作了一些助手(显示 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;
}
}
【问题讨论】:
-
是的,我尝试了一些看起来很像两个答案的东西。最大的问题是(你可以在我的视频中看到),当我到达“顶部”时(当前向指向 Vector3.up 时),Y 和 Z 都从 0 变为 180,而 X 以相反的顺序变为它只是他妈的我的夹紧。四元数不是那么容易理解:x
-
也许我应该只做一个 Rotate() 或其他事情,而不是 LookAt + 试图在之后进行夹紧。但我不知道如何实现这一点,所以我可以按照我的需要去做。 (理想情况下,我可以使用 3 个布尔值“锁定”,这样我就可以选择我可以/不能在哪个轴上旋转,但是嘿,如果我找到一个单轴的解决方案,它仍然会很棒
标签: c# unity3d math quaternions