在VR环境下,移动、缩放、旋转某个物体时,由于体验者所在位置和朝向不一样,同一物体可能位于相机的前后左右上下的各个方向。
比如用VR手柄进行平移操作时,向前推摇杆是将物体调远,向后推摇杆调近物,如果只是简单地加减z坐标,站上物体前方和后方的操作是反的。用户体验很不好。
如果可以求得物体哪个坐标轴与相机正前方相近,就按坐标轴方向移动,这个问题就解决了。
//获取与相机前右上三个方向相对应的物体的三个坐标轴
private void GetObjAxisesReferToCamera(bool isLocal,out Vector3 vecForward, out Vector3 vecRight, out Vector3 vecUp)
{
Vector3 vecCamForward = Vector3.ProjectOnPlane(Camera.main.transform.forward, Vector3.up);
Vector3 vecCamLeft = Quaternion.Euler(0, 90, 0) * vecCamForward;
//物体的六个坐标轴与相机的三个方向夹角检测
Vector3[] vecList = new Vector3[6];
vecList[0] = _curHle.transform.forward;
vecList[1] = -vecList[0];
vecList[2] = _curHle.transform.right;
vecList[3] = -vecList[2];
vecList[4] = _curHle.transform.up;
vecList[5] = -vecList[4];
float minForwardAngle = 360.0f;
float minRightAngle = 360.0f;
float minUpAngle = 360.0f;
vecForward = vecList[0];
vecRight = vecList[0];
vecUp = vecList[0];
for (int i = 0; i < vecList.Length; i++)
{
float a = Vector3.Angle(vecCamForward, vecList[i]);
if (a < minForwardAngle)
{
minForwardAngle = a;
vecForward = vecList[i];
}
float b = Vector3.Angle(vecCamLeft, vecList[i]);
if (b < minRightAngle)
{
minRightAngle = b;
vecRight = vecList[i];
}
float c = Vector3.Angle(Vector3.up, vecList[i]);
if (c < minUpAngle)
{
minUpAngle = c;
vecUp = vecList[i];
}
}
//缩放时用到的本地坐标系,需要将坐标轴转换到本地
if(isLocal)
{
vecForward = _curHle.transform.InverseTransformDirection(vecForward);
vecRight = _curHle.transform.InverseTransformDirection(vecRight);
vecUp = _curHle.transform.InverseTransformDirection(vecUp);
}
}
使用
//前后缩放
_curHle.transform.localScale += vecForwardMin * vec2DAxis.y * Time.deltaTime;
//左右缩放
_curHle.transform.localScale += vecRightMin * vec2DAxis.x * Time.deltaTime;
//上下缩放
_curHle.transform.localScale += vecUpMin * vec2DAxis.y * Time.deltaTime;