[Tutorial] 3. Grabbing objects
Updated: May 18
In this tutorial we will implement grabbing objects with the motion controllers using the VRExpansionPlugin.
The first thing to do is to get the closest object, that overlaps with our hands. Add a sphere collision component to the left and the right motion controllers. Call them GrabSphereLeft and GrabSphereRight. On the details panel set their radius to 8.
1.Add collision spheres
2. Get nearest overlapping object
Now let's create a new function that will simply return the first actor, that overlaps with our grab sphere. Add a new function, call it GetNearestActor. Give it an input called GrabSphere, of type Sphere Collision and an output called Actor, of type Actor.
The result should look like this:
Now let's add the functionality to return the first overlapping object. We will get an array of all objects that overlaps with the sphere, then we check if the object is grippible, that is, implements the VRGripInterface. Then we return the first object found:
Now we need to make another function, that will actually grab the actor returned by this function. Make a new function call it GrabOverlappingActor. It will need two inputs. The first is called Hand of type GripMotionControllerComponent. The other one is called GrabSphere of type Sphere Collision.
From this function we need to call our previously created GetNearestActor function, passing in the GrabSphere reference:
After that, we check if the returned actor is valid, then we simply call the GripObjectByInterface function. Drag out the Hand input parameter and type GripObjectByInterface:
This function needs two more parameters to work. An Object to Grip, so connect to the returned actor of our GetNearestActor function to the Object to Grip. The other parameter is the world offset. Drag out the hand again from the main function and type ConvertToControllerRelativeTransform. This function also needs an input(In Transform). Drag out our actor from the GetNearestActor function and call it GetActorTransform. Connect the returned transform to the hand transform. Connect the combined return value to World Offset. The result should look like this:
It's a bit of a spaghetti, but hey, it works. The gripping part is done, we just need to call this function when we press the grip button. So let's go back to the Event Graph of our VRPawn and call this function when we press the button. We need to pass in the MotionController component and the corresponding GrabSphere. Do it for both hands.
Let's test how it works. To do that, we need an object that implements the VRGripInterface. For the test, I will just use the potion, which comes with the plugin. You can find it under VRExpansion/Potion/. Drop it in the scene, make sure you put the blueprint class called PotionActor, not the static mesh. Hit play and try to grab it:
It works, but it doesn't drop on release so let's fix that. Create a new function called DropAllGrips. Add an input paramater called Hand of type GripMotionControllerComponent. Just like our GrabOverlappingActor function, but we don't want any output this time. In this function check if the Hand has any gripped objects, If it has, then get all gripped actors from the hand, and drop them all.
The final step is to call this function when we release the button, don't forget to pass in the controller component: