Apr 20 • Ashray Pai

Oculus Hand Interaction: Two Hand Grab and Physics Objects

This blog post is the continuation of the previous post where we've learned about adding hand interactors and interactable objects that can be manipulated using just one hand. If you haven’t checked out the first part of this series, we highly recommend checking it out.

In this blog, we’ll learn about two things. To create objects that can be interacted with two hands and to create objects with physics.

Two Hand Interaction

Generally, we’ll use two hands to scale an object. This type of interaction can be used to represent a heavy object as well i.e. requiring both the hands to pick up something heavy. So to create such an object:

  • Create a cube GameObject with a Rigidbody, Grabbable and Hand Grab Interactable components attached to it.
  • Under the Grabbable component make sure the box for the parameter Transfer Hand On Second Grab is unchecked.
  • Under the Hand Grab Interactable component, we’ll select the Snap Type parameter as None.
  • Add the component Two Grab Free Transformer to the GameObject → Drag and drop this component into the Two Grab Transformer parameter of the Grabbable component.
  • Rename the GameObject to CubeTwoHandsInteraction → rescale and reposition it.
  • Now we can set up the Two Grab Free Transformer component as per our requirements:
    • If we want to move the object with two hands without allowing for a change in size then, check the box ✅ for the Constraint parameters for both Min Scale and Max Scale → enter the same value as that of the scale on x-axis.
You can now play the scene and test it. While doing so you might notice that the object snaps into one hand and the interaction doesn't feel natural. This problem will be addressed later on in this blog.
  • Now if we want to scale the object then all we have to do is change the Min Scale and Max Scale values i.e different from the current x-axis scale.
Once again you can play the scene and test it. 
  • You might wonder what the parameter ‘Constraints Are Relative’ does? And you might also wonder, what if the scale values are different for different axis? Well, I will help you understand that with a simple calculation for each of the four possible cases. For all the cases we’ll consider the Min Scale Value as 0.1 and Max scale value as 0.3, we’ll just vary the parameter Constraints Are Relative and the scale of the object.
    • Case 1: The parameter Constraints Are Relative is checked and the scale values on all axis are the same.

      Axis Initial Scale Value Runtime Min Scalable Value Runtime Max Scalable Value
      X 0.2 0.02 0.06
      Y 0.2 0.02 0.06
      Z 0.2 0.02 0.06

      From the table, you can notice that the Min Scale and Max Scale values are multiplied by the initial scale value of all the axis

    • Case2: The parameter Constraints Are Relative is unchecked and the scale values on all axis are the same

      Axis Initial Scale Value Runtime Min Scalable Value Runtime Max Scalable Value
      X 0.2 0.1 0.3
      Y 0.2 0.1 0.3
      Z 0.2 0.1 0.3

      From the table, you can notice that the object scale is limited to the Min Scale and Max Scale values.

    • Case 3: The parameter Constraints Are Relative is checked and the scale values on all axis are different

      Axis Initial Scale Value Runtime Min Scalable Value Runtime Max Scalable Value
      X 0.2 0.02 0.06
      Y 0.3 0.03 0.09
      Z 0.1 0.01 0.03

      From the table, you can see that the Min Scale and Max Scale values are multiplied by the initial scale value of all the axis.

    • Case 4: The parameter Constraints Are Relative is unchecked and the object scale values on all axis are different

      Axis Initial Scale Value Runtime Min Scalable Value Runtime Max Scalable Value
      X 0.2 0.1 0.3
      Y 0.3 0.15 0.45
      Z 0.1 0.05 0.15

      From the table, you can notice that the object scale values on the Y and the Z axes are relative to the X-axis. The calculation is done using cross-multiplying proportions method.

  • Now to fix the problem of the object snapping into one hand:
    • Select the CubeTwoHandsInteractable GameObject → create an empty GameObject as a child → name it as AttachPoint .
    • Add the components Hand Grab Point and Collider Surface.
    • Drag and drop the CubeTwoHandsInteractable GameObject into the Collider parameter of the Collider Surface component. This will automatically select the box collider.
    • Drag and drop the Collider Surface component into the surface parameter of the component Hand Grab Point → uncheck the Use Hand Pose parameter.
    • Drag and drop the AttachPoint GameObject into the Relative To parameter of the Hand Grab Point component.
    • Finally, drag and drop the AttachPoint GameObject into the Hand Grab Points parameter of the Hand Grab Interactable component.
You can test the scene and see the difference, it feels more natural now.
With that, we have completed two hands interaction.

Adding Physics

We all know how physics works on a GameObject with a Rigidbody component. But when it comes to hand interaction, interacting with such an object is not possible. Because every time we try to grab it, the object will fall down. There has to be some way the physics gets disabled when interacting with a hand and enabled when released. And that’s done with the help of the Physics Grabbable component. So to create an interactable object with physics:

  • Create a Sphere GameObject → adjust its position and scale → add Rigidbody, Grabbable and Hand Grab Interactable components to it.
  • Add the Physics Grabbable component and test the scene. You will notice that the object can be grabbed and dropped, but it cannot be thrown.
  • In order to be able to throw an object, we require components that can calculate the velocity of the hand and apply it to the object when released :
    • On the Hierarchy window, navigate to OculusInteractionSampleRigInputOCRHandsLeft Hand.
    • Create an empty GameObject → Rename it as VelocityCalculatorLeft → Add the components HandPoseInputDevice and StandardVelocityCalculator
    • Drag and drop LeftHand into the Hand parameter of the HandPoseInputDevice component.
    • Drag and drop the HandPoseInputDevice component into the Throw Input Device parameter of the StandardVelocityCalculator component.
  • Drag and drop the VelocityCalculatorLeft GameObject into the Velocity Calculator parameter of the Hand Grab Interactor component.
  • Select the Sphere GameObject, drag and drop the PhysicsGrabbable component into the Physics Grabbable parameter of the HandGrabInteractable component.
  • Add velocity calculation to the Right Hand as well by following the same steps as above.
  • Now when we test our scene, we’ll be able to grab and throw the object.
💡Note : For better grab interaction, we can select the Collision Detection parameter of the Rigidbody component as Continuous. So that even if the hand is moving fast towards to grab it collision detection will be detected even if the collision occurs between two FixedUpdate steps.
With that, we have learned to create objects with physics. 

Conclusion 

We can create objects that can be either interacted with one hand or two hands, we just need to make sure all the required components are attached to that object. It’s really amazing when you can grab an object, resize it with two hands and throw it around. One of the applications I can think of is puzzles where you can resize a key to fit it correctly into a lock. In the next part, we’ll learn about rotational transforms and recording hand poses.

Thanks for reading this blog post 🧡

If you've enjoyed the insights shared here, why not spread the word? Share the post with your friends and colleagues who might also find it valuable.
Your support means the world to us and helps us create more content you'll love.