我正在做一个 VR 项目,我正在努力做一些不应该那么难的事情,但我真的不擅长数学:x
我想做的是在世界上有“物理”按钮,我可以用手指按下/松开它,这部分效果非常好,感觉很完美,但是:
目前,要“按下”按钮,我使用的是控制器的 z delta 位置,所以我不能从顶部按下按钮,因为我需要 y delta。
我试图让按钮面向任何方向,并能够使用控制器的右轴推动它们,但无法绕开它:x
我需要能够根据它的位置/旋转按下按钮。
我不知道它是否真的可以理解(可能不是),也许我只是错过了一些非常明显的东西。
这是我的按钮代码,枚举部分可能没用,我只是在尝试,哈哈
using System;
using UnityEngine;
public class JVRButton : MonoBehaviour, IJVRFingerInteract
{
[SerializeField] private Vector3 pressedPosition;
[SerializeField] private Vector3 defaultPosition;
[SerializeField] private Vector3 unpressPosition;
[SerializeField] private LinearDragNormal direction;
public bool Pressed { get; private set; }
public event Action<bool> OnStateChange;
private bool _changedState;
private Transform _transform;
private Vector3 _tmp;
private float _delay;
private float _delta;
private void Awake()
{
_transform = transform;
_transform.localPosition = Pressed ? pressedPosition : defaultPosition;
}
private void Update()
{
_delay += Time.deltaTime;
if (_delay < 0.1f) return;
// "Spring" effect
_transform.localPosition = Vector3.MoveTowards(_transform.localPosition, Pressed ? pressedPosition : defaultPosition, Time.deltaTime / 2);
}
public void JVRFingerInteract(JVRFinger jvrFinger)
{
Vector3 test = Quaternion.FromToRotation(jvrFinger.transform.forward, _transform.forward).eulerAngles;
Debug.Log(test);
switch(direction)
{
case LinearDragNormal.XPositive:
_delta = Mathf.Min(jvrFinger.JVRController.DeltaPositionLocal.z, 0);
break;
case LinearDragNormal.XNegative:
_delta = Mathf.Max(jvrFinger.JVRController.DeltaPositionLocal.z, 0);
break;
case LinearDragNormal.YPositive:
_delta = Mathf.Max(jvrFinger.JVRController.DeltaPositionLocal.y, 0);
break;
case LinearDragNormal.YNegative:
_delta = Mathf.Min(jvrFinger.JVRController.DeltaPositionLocal.y, 0);
break;
case LinearDragNormal.ZPositive:
_delta = Mathf.Min(jvrFinger.JVRController.DeltaPositionLocal.x, 0);
break;
case LinearDragNormal.ZNegative:
_delta = Mathf.Max(jvrFinger.JVRController.DeltaPositionLocal.x, 0);
break;
default:
throw new ArgumentOutOfRangeException();
}
MoveButton(Pressed ? unpressPosition : pressedPosition);
}
private void MoveButton(Vector3 position)
{
if (_changedState && _delay < 0.5f) return;
_delay = 0;
_changedState = false;
_tmp = _transform.localPosition;
_tmp = Vector3.MoveTowards(_tmp, position, _delta);
if (_tmp.x < position.x) _tmp.x = position.x;
if (_tmp.y < position.y) _tmp.y = position.y;
if (_tmp.z < position.z) _tmp.z = position.z;
_transform.localPosition = _tmp;
if (_transform.localPosition == pressedPosition)
{
Pressed = true;
_changedState = true;
OnStateChange?.Invoke(Pressed);
}
else if (_transform.localPosition == unpressPosition)
{
Pressed = false;
_changedState = true;
OnStateChange?.Invoke(Pressed);
}
}
}
public enum LinearDragNormal
{
XPositive,
XNegative,
YPositive,
YNegative,
ZPositive,
ZNegative
}
JVRFingerInteract 在我的手指触摸按钮的每一帧都被调用,我只是在手指上做一个重叠球来获得可交互的对象。
按钮的推动轴是按钮的局部 Z 轴,正 Z 指向按钮表面。