I’m writing my own library to handle grabbing objects in VR.
I am using the method that changes the velocity and angular velocity of the held object every FixedUpdate based on the difference between the held object’s position and rotation to the controller’s position and rotation respectively.
The item that can be held has the following hierarchy
Part 1 and Part 2 are simple meshes, that each have a box collider. hold position 1 and hold position 2 are empty game objects that mark locations the player can grab the object at. When the player grabs the item I calculated which hold position is closest to the hand then reposition the ‘item components’ GameObject according to the local position of the appropriate hold position (‘item component’ strictly exists to be repositioned within ‘item’). ‘item’ has the only rigidbody component… This all works fine. The item can be picked up and it can be held at two locations.
However the movement of the item is jittery if it is held at a hold position that is not located at the origin of the ‘item’ GameObject.
I have ‘hold position 1’ located near the origin, and the movement of the object is smooth when the item is held at this location (e.g. the ‘item components’ object has a local position of 0,0,0).
I have ‘hold position 2’ located about half a meter below the origin of the the ‘item’ GameObject and the item’s movement is jittery (e.g. in this case the ‘item components’ object has a local position of about 0,0.5,0, which places the meshes and colliders of the item further up in relation to the hand).
I thought this may be tied to center of mass and inertia tensor. So I called ResetCenterOfMass and ResetInertiaTensor on the rigid body after I moved the 'item component’s position and rotation. But I saw no different in the resulting behavior.
The parent gameobject of the item has code with the following FixedUpdate
void FixedUpdate()
if (isHeld)
{
rigidb.velocity = (temp.GetPalm().transform.position - transform.position) * speed / Time.fixedDeltaTime;
rigidb.maxAngularVelocity = maxAngularVelocity;
Quaternion deltaRot = temp.GetPalm().transform.rotation * Quaternion.Inverse(transform.rotation);// transform.rotation);
Vector3 eulerRotShortestDistance = new Vector3(Mathf.DeltaAngle(0, deltaRot.eulerAngles.x), Mathf.DeltaAngle(0, deltaRot.eulerAngles.y), Mathf.DeltaAngle(0, deltaRot.eulerAngles.z));
eulerRotShortestDistance *= Mathf.Deg2Rad;
rigidb.angularVelocity = eulerRotShortestDistance * rotSpeed / Time.fixedDeltaTime;
}
}
When I pick up the object I run a function that repositions the children objects (that are the 3D models that make up the object)
public void BeginHold(HandController hand)
{
//orient children gameobjects so hand hold location is at parent gameobject's origin
if(GetHoldForGivenHand(hand, out Transform tform))
{
objectComponents.transform.localPosition = -tform.localPosition;
objectComponents.transform.localRotation = tform.localRotation;
//rigidb.ResetCenterOfMass();
//rigidb.ResetInertiaTensor();
}
else
{
Debug.LogError("could not find current hand hold");
}
isHeld = true;
}