问题
I am trying to lock the models hands to an object when an object is grabbed. Currently the object in my project has been locked to only allow for movement in the Y and Z axis when it is grabbed. I want to lock the players hand position in the X axis when the object is grabbed but return to regular hand tracking when released. (An Example of this is grabbing a door knob in VR, you want the hand to stay fixed to the door knob until released)
I have tried playing around with parenting the hands to the object but I may have not done it right. I have made some modifications to the OVRGrabber script to work with my project. The sampled code below is being added to the VRMirror script which can be found here. lockHands() is called at the end of the fixed update.
void lockHands()
{
if(L_GrabbedObject.GetComponent<OVRGrabber>().isGrabbed || R_GrabbedObject.GetComponent<OVRGrabber>().isGrabbed)
{
if (mirrorLeft)
{
string name = L_GrabbedObject.GetComponent<OVRGrabber>().m_grabbedObj.name;
Debug.Log(name + " Left");
}
else if (mirrorRight)
{
var objGrabbed = R_GrabbedObject.GetComponent<OVRGrabber>().m_grabbedObj;
string name = objGrabbed.name;
Debug.Log(name + " Right");
}
}
}
I need this part to work along side the Bilateral mirroring script as well with the OVRGrabber and OVRCameraRig.
Plate is the object being grabbed. Here is a screenshot of the project:
回答1:
The solution I came up with uses the OVRCameraRig script. I made a bunch of changes to that scrip in the UpdateAnchors() method.
var mirror = GameObject.Find("OVRCameraRig").GetComponent<VRMirror>();
var L_GrabbedObject = GameObject.Find("Left Hand Target").GetComponent<OVRGrabber>();
var R_GrabbedObject = GameObject.Find("Right Hand Target").GetComponent<OVRGrabber>();
//Need this for controller offset because if we're on OpenVR, we want to set the local poses as specified by Unity, but if we're not, OVRInput local position is the right anchor
if (OVRManager.loadedXRDevice == OVRManager.XRDevice.OpenVR)
{
Vector3 leftPos = Vector3.zero;
Vector3 rightPos = Vector3.zero;
Quaternion leftQuat = Quaternion.identity;
Quaternion rightQuat = Quaternion.identity;
if (mirror.mirrorLeft)
{
if (OVRNodeStateProperties.GetNodeStatePropertyVector3(Node.LeftHand, NodeStatePropertyType.Position, OVRPlugin.Node.HandLeft, OVRPlugin.Step.Render, out leftPos))
if(L_GrabbedObject.isGrabbed)
{
if(L_GrabbedObject.m_grabbedObj.name == "rollingPin")
{
Vector3 leftHand = leftHandAnchor.localPosition;
leftHand.z = leftPos.z;
leftHandAnchor.localPosition = leftHand;
}
}else
{
leftHandAnchor.localPosition = leftPos;
}
if (OVRNodeStateProperties.GetNodeStatePropertyQuaternion(Node.LeftHand, NodeStatePropertyType.Orientation, OVRPlugin.Node.HandLeft, OVRPlugin.Step.Render, out leftQuat))
if (!L_GrabbedObject.isGrabbed)
leftHandAnchor.localRotation = leftQuat;
}else if (mirror.mirrorRight)
{
if (OVRNodeStateProperties.GetNodeStatePropertyVector3(Node.RightHand, NodeStatePropertyType.Position, OVRPlugin.Node.HandRight, OVRPlugin.Step.Render, out rightPos))
if (R_GrabbedObject.isGrabbed)
{
if (R_GrabbedObject.m_grabbedObj.name == "rollingPin")
{
Vector3 rightHand = rightHandAnchor.localPosition;
rightHand.z = rightPos.z;
rightHandAnchor.localPosition = rightHand;
}
}
else
{
rightHandAnchor.localPosition = rightPos;
}
if (OVRNodeStateProperties.GetNodeStatePropertyQuaternion(Node.RightHand, NodeStatePropertyType.Orientation, OVRPlugin.Node.HandRight, OVRPlugin.Step.Render, out rightQuat))
if (!R_GrabbedObject.isGrabbed)
{
rightHandAnchor.localRotation = rightQuat;
}
}
}
else
{
if (mirror.mirrorLeft)
{
if (L_GrabbedObject.isGrabbed)
{
if (L_GrabbedObject.m_grabbedObj.name == "rollingPin")
{
Vector3 leftHand = leftHandAnchor.localPosition;
leftHand.z = OVRInput.GetLocalControllerPosition(OVRInput.Controller.LTouch).z;
leftHandAnchor.localPosition = leftHand;
}
}
else
{
leftHandAnchor.localPosition = OVRInput.GetLocalControllerPosition(OVRInput.Controller.LTouch);
leftHandAnchor.localRotation = OVRInput.GetLocalControllerRotation(OVRInput.Controller.LTouch);
}
}else if (mirror.mirrorRight) {
if (R_GrabbedObject.isGrabbed)
{
if (R_GrabbedObject.m_grabbedObj.name == "rollingPin")
{
Vector3 rightHand = rightHandAnchor.localPosition;
rightHand.z = OVRInput.GetLocalControllerPosition(OVRInput.Controller.RTouch).z;
rightHandAnchor.localPosition = rightHand;
}
}
else
{
rightHandAnchor.localPosition = OVRInput.GetLocalControllerPosition(OVRInput.Controller.RTouch);
rightHandAnchor.localRotation = OVRInput.GetLocalControllerRotation(OVRInput.Controller.RTouch);
}
}
}
I also had to make the m_grabbedObj from OVRGrabber script public, as well as I added a public bool to the OVRGrabber script that will switch between true and false if an object is grabbed or not. (The object must have the OVRGrabbable script on it).
The reason I check for the name of the object is because certain objects have their movements locked to certain axis. The plate in my game can only be moved in the Z and Y axis.
The issue I am having still
When you let go of the object the hand of the player will snap to the position that the controller is in base on world.
来源:https://stackoverflow.com/questions/57275200/unity-oculus-locking-hand-positions-in-1-axis-while-allowing-for-movement-in-the