WEBVTT 1 00:00:04.325 --> 00:00:08.925 Realistic Immersion Advanced Edition VR project implementation 1 2 00:00:23.925 --> 00:00:26.675 We'll now try to implement 3 00:00:26.675 --> 00:00:28.475 grabbing and lifting objects 4 00:00:28.475 --> 00:00:30.725 placed in the world space 5 00:00:30.725 --> 00:00:32.675 by hand 6 00:00:32.675 --> 00:00:35.725 Additionally, we will practice both lifting objects 7 00:00:35.725 --> 00:00:38.875 while maintaining the grabbed position and using a snap feature 8 00:00:38.875 --> 00:00:43.025 where objects attach to a specific position 9 00:00:43.025 --> 00:00:45.675 on the hand when grabbed 10 00:00:45.675 --> 00:00:49.625 We will also spend time implementing a feature 11 00:00:49.625 --> 00:00:52.375 that applies animations of the hand opening and closing 12 00:00:52.375 --> 00:00:54.875 based on the VR controller's input state 13 00:00:54.875 --> 00:00:57.875 making the act of grabbing and releasing objects appear more natural 14 00:00:57.875 --> 00:01:01.875 Applying Hand Animation 15 00:01:02.375 --> 00:01:05.875 Let's continue from where we left off last time 16 00:01:05.875 --> 00:01:09.075 When we grab or throw an object 17 00:01:09.075 --> 00:01:10.875 we usually grasp it 18 00:01:10.875 --> 00:01:15.925 as if we were clenching our hand to give it a more realistic feel 19 00:01:15.925 --> 00:01:19.225 To create the effect of grasping 20 00:01:19.225 --> 00:01:22.075 we will add a simple animation to the hand 21 00:01:22.075 --> 00:01:25.925 And let's start by focusing on the right hand for now 22 00:01:27.875 --> 00:01:33.975 Let's start by creating the input keys first 23 00:01:33.975 --> 00:01:37.475 Right-click on Inputs and 24 00:01:37.475 --> 00:01:40.775 add an Input Action to Input 25 00:01:40.775 --> 00:01:51.625 and name it IA_HandTrigger_Right 26 00:01:53.225 --> 00:01:56.125 Since we only need the Right Hand Trigger to detect 27 00:01:56.125 --> 00:02:00.375 when it's pressed and released when grabbing 28 00:02:00.375 --> 00:02:02.775 let's set it to digital input mode 29 00:02:02.775 --> 00:02:06.175 We'll receive values as True or False for this input 30 00:02:06.175 --> 00:02:08.775 Add another mapping 31 00:02:08.775 --> 00:02:11.479 in the Input Mapping Context 32 00:02:11.479 --> 00:02:22.479 and select IA_HandTrigger_Right 33 00:02:23.775 --> 00:02:28.125 Let's select the Right Grip button 34 00:02:28.125 --> 00:02:32.360 on the Oculus Touch for the key 35 00:02:32.360 --> 00:02:34.375 This will now correspond to True or False values 36 00:02:35.625 --> 00:02:38.725 Let's save it for now 37 00:02:38.725 --> 00:02:44.425 Let's go ahead and add a few more keys while we're at it 38 00:02:44.425 --> 00:02:46.425 To express animations 39 00:02:46.425 --> 00:02:51.875 we need to remember how our index, middle, and other fingers moved, right? 40 00:02:51.875 --> 00:02:55.575 So, let's add an Input Action to Input 41 00:02:55.575 --> 00:03:06.325 and name it IA_IndexTrigger_Right 42 00:03:07.625 --> 00:03:11.625 For the Index Trigger, we'll set the Value Type 43 00:03:11.625 --> 00:03:13.675 to Axis1D (float) 44 00:03:13.675 --> 00:03:16.125 so it can detect how much it's pressed 45 00:03:16.125 --> 00:03:19.325 allowing animations to correspond to the degree of pressure applied 46 00:03:22.625 --> 00:03:27.325 If we're going to receive it as a float anyway, let's change the name accordingly 47 00:03:27.325 --> 00:03:31.475 Let's distinguish between True/False 48 00:03:31.475 --> 00:03:34.975 and Float here by adding "Float" to the name 49 00:03:34.975 --> 00:03:40.449 So it will be named IndexTriggerFloat_Right 50 00:03:41.475 --> 00:03:46.625 Let's proceed to add an Input Action 51 00:03:46.625 --> 00:03:59.325 named IA_HandTriggerFloat_Right in Input 52 00:03:59.325 --> 00:04:02.725 I'll add three things 53 00:04:02.725 --> 00:04:04.525 Index Trigger Float for the right hand 54 00:04:04.525 --> 00:04:07.275 Hand Trigger Float for the right hand 55 00:04:07.275 --> 00:04:09.925 and True/False Boolean values 56 00:04:09.925 --> 00:04:12.375 Since Hand Trigger Float will also be received as a float 57 00:04:12.375 --> 00:04:16.225 let's set it to Axis1D (float) 58 00:04:16.225 --> 00:04:18.825 for one-dimensional coordinates 59 00:04:19.925 --> 00:04:23.725 Then, since it's a Skeletal Mesh 60 00:04:23.725 --> 00:04:26.475 for the right hand's Skeletal Mesh 61 00:04:26.475 --> 00:04:30.425 there's an Anim Class where we can set up animations 62 00:04:32.276 --> 00:04:35.426 Considering the time, we won't create a new one from scratch 63 00:04:35.426 --> 00:04:38.826 We'll try using animations 64 00:04:38.826 --> 00:04:42.026 that were already present in the VR template 65 00:04:42.026 --> 00:04:44.276 The animations should be located under Characters here 66 00:04:44.276 --> 00:04:48.426 In the Characters folder, inside MannequinsXR 67 00:04:48.426 --> 00:04:50.976 there's a folder named Animations 68 00:04:50.976 --> 00:04:54.576 So, here you'll find animations related to the hand movements 69 00:04:54.576 --> 00:04:56.526 These animation files are used to blueprint 70 00:04:56.526 --> 00:04:59.440 within the Meshes folder 71 00:04:59.440 --> 00:05:02.290 where you can find 72 00:05:02.290 --> 00:05:05.976 the MannequinsXR animation file 73 00:05:05.976 --> 00:05:10.176 We'll use these to apply animations to our hands 74 00:05:10.176 --> 00:05:14.976 So, we'll duplicate this by using Ctrl + D 75 00:05:14.976 --> 00:05:22.526 Let's name this ABP_HunetHand then 76 00:05:26.026 --> 00:05:29.426 I duplicated it with the name HunetHand 77 00:05:32.276 --> 00:05:36.876 I created a new folder named Animations in Content 78 00:05:36.876 --> 00:05:45.676 and placed the HunetHand file inside 79 00:05:45.676 --> 00:05:49.626 I'll move the duplicated HunetHand file 80 00:05:49.626 --> 00:05:52.926 to the Animations folder here 81 00:05:55.876 --> 00:05:59.526 I'll place the ABP_HunetHand animation blueprint file 82 00:05:59.526 --> 00:06:03.326 we just created 83 00:06:05.726 --> 00:06:08.726 using this file into 84 00:06:08.726 --> 00:06:12.176 the Animations folder 85 00:06:14.876 --> 00:06:18.776 If you double-click to open the animation blueprint file 86 00:06:18.776 --> 00:06:23.426 you'll see that it's already partially implemented 87 00:06:23.426 --> 00:06:27.876 If you look at the values, in the preview section here 88 00:06:27.876 --> 00:06:31.326 you'll see things like Pose Alpha Grasp, followed by Index Curl Point 89 00:06:31.326 --> 00:06:32.926 Thumb Up, and so on 90 00:06:32.926 --> 00:06:35.376 So just by looking at the name 91 00:06:35.376 --> 00:06:39.726 Index Curl refers to when the index finger curls upwards 92 00:06:39.726 --> 00:06:42.526 Alpha Grasp would refer to when making a fist 93 00:06:42.526 --> 00:06:45.076 and Thumb Up would correspond to 94 00:06:45.076 --> 00:06:46.076 when the thumb is raised 95 00:06:46.076 --> 00:06:49.176 Go ahead and try changing some values here 96 00:06:49.176 --> 00:06:51.526 If you increase the Pose Alpha Grasp value 97 00:06:51.526 --> 00:06:54.376 what would happen? 98 00:06:54.376 --> 00:06:58.826 The Pose Alpha Grasp value typically ranges from 0 to 1 99 00:06:58.826 --> 00:07:04.626 influencing the positions of multiple fingers 100 00:07:04.626 --> 00:07:07.326 like index, middle, and ring fingers 101 00:07:07.326 --> 00:07:11.826 We can use the float value 102 00:07:11.826 --> 00:07:13.126 from our right hand's HandTrigger to control this Pose Alpha Grasp value 103 00:07:13.126 --> 00:07:17.376 allowing us to represent a range from 0 to 1 104 00:07:17.376 --> 00:07:20.926 Below that, there's Pose Alpha Index Curl 105 00:07:20.926 --> 00:07:23.676 Pose Alpha Index Curl also allows you to bend and straighten the index finger 106 00:07:23.676 --> 00:07:26.726 using a value ranging from 0 to 1 107 00:07:28.976 --> 00:07:36.576 So, to effectively use finger animations 108 00:07:36.576 --> 00:07:40.226 we'll use Pose Alpha Grasp and Pose Alpha Index Curl values to apply animations 109 00:07:40.226 --> 00:07:42.276 Let's give it a try 110 00:07:42.276 --> 00:07:46.326 The rest, you can experiment with by adjusting them 111 00:07:46.326 --> 00:07:50.376 based on when, how, and which inputs you want to use 112 00:07:50.376 --> 00:07:52.576 to control the values 113 00:07:52.576 --> 00:07:55.876 Let's focus on showing these two first 114 00:07:58.226 --> 00:08:02.726 Then let's head over to the Hunet Player 115 00:08:02.726 --> 00:08:06.126 where in BeginPlay 116 00:08:07.376 --> 00:08:10.126 we'll store the initial animation blueprint values 117 00:08:10.126 --> 00:08:12.526 So, we'll get the animation instance 118 00:08:12.526 --> 00:08:15.176 from the right hand's Anim Instance 119 00:08:16.976 --> 00:08:25.926 to directly pass values 120 00:08:25.926 --> 00:08:30.776 to the animation blueprint 121 00:08:30.776 --> 00:08:33.926 We'll cast the result of Get Anim Instance 122 00:08:33.926 --> 00:08:38.576 We'll cast it to the ABP_HunetHand 123 00:08:38.576 --> 00:08:40.326 that we created 124 00:08:44.476 --> 00:08:49.626 So, we'll store this casted ABP_HunetHand 125 00:08:49.626 --> 00:08:52.426 as a variable 126 00:08:54.076 --> 00:08:55.976 Let's name this variable 127 00:08:59.776 --> 00:09:06.526 RightHandAnim 128 00:09:07.876 --> 00:09:11.026 We'll name the variable RightHandAnim without spaces 129 00:09:11.026 --> 00:09:14.526 It's generally better to avoid spaces in variable names 130 00:09:14.526 --> 00:09:16.476 so we'll name it accordingly 131 00:09:21.576 --> 00:09:25.326 Now that we've stored the variables 132 00:09:25.326 --> 00:09:29.276 we just need to pass values 133 00:09:29.276 --> 00:09:31.026 to each of them 134 00:09:31.026 --> 00:09:35.776 So, let's add an event below for this 135 00:09:35.776 --> 00:09:45.776 We'll receive the IA_HandTriggerFloat_Right event 136 00:09:45.776 --> 00:09:49.726 and continuously pass its values to RightHandAnim 137 00:09:49.726 --> 00:09:52.960 while the event is pressed 138 00:09:52.960 --> 00:09:55.110 So, we'll use Get RightHandAnim to retrieve RightHandAnim 139 00:09:55.110 --> 00:09:57.510 to retrieve RightHandAnim 140 00:09:57.510 --> 00:10:10.160 and then continuously pass this value 141 00:10:10.160 --> 00:10:13.076 to Set Pose Alpha Grasp 142 00:10:13.076 --> 00:10:15.876 We'll pass the Action Value 143 00:10:15.876 --> 00:10:17.776 to Set Pose Alpha Grasp like this 144 00:10:20.026 --> 00:10:24.676 Similarly, let's duplicate it with Ctrl + D 145 00:10:24.676 --> 00:10:27.176 then ensure to also pass the Action Value to Set Pose Alpha Grasp 146 00:10:27.176 --> 00:10:30.226 when releasing the hand at the end 147 00:10:30.226 --> 00:10:34.326 To ensure it perfectly resets to 0 148 00:10:34.326 --> 00:10:38.276 we should also target the RightHandAnim variable in this duplicated event 149 00:10:43.026 --> 00:10:46.326 We'll do the same for the index finger as well 150 00:10:46.326 --> 00:10:55.776 For IA_IndexTriggerFloat_Right 151 00:10:57.376 --> 00:11:01.726 we'll also retrieve RightHandAnim 152 00:11:01.726 --> 00:11:08.626 and use Set Pose Alpha Index Curl 153 00:11:08.626 --> 00:11:13.826 to pass the Action Value like this 154 00:11:13.826 --> 00:11:20.176 Of course, we'll duplicate it with Ctrl + D 155 00:11:21.676 --> 00:11:24.726 connect it to the same target for when the action is completed 156 00:11:24.726 --> 00:11:27.026 and pass the Action Value of 0 157 00:11:27.026 --> 00:11:30.626 to ensure the hand fully extends 158 00:11:32.076 --> 00:11:34.926 Let's compile and save the changes 159 00:11:34.926 --> 00:11:38.476 Next, we need to link this event to the Input Mapping Context 160 00:11:38.476 --> 00:11:41.926 as we've only created the event so far 161 00:11:41.926 --> 00:11:44.476 We'll add two mappings 162 00:11:44.476 --> 00:11:45.976 to the Input Mapping Context 163 00:11:45.976 --> 00:11:56.976 The first one will be IA_HandTriggerFloat_Right 164 00:11:56.976 --> 00:12:02.776 and we'll map it to the Right Grip Axis 165 00:12:02.776 --> 00:12:05.776 on the Oculus Touch 166 00:12:07.826 --> 00:12:10.376 Then, we'll add one more 167 00:12:12.176 --> 00:12:15.626 and collapse any unnecessary sections for clarity 168 00:12:21.176 --> 00:12:29.676 We'll add IA_IndexTriggerFloat_Right next 169 00:12:29.676 --> 00:12:33.926 and we'll assign it to the Trigger Axis 170 00:12:33.926 --> 00:12:39.326 on the Oculus Touch Right controller 171 00:12:39.326 --> 00:12:41.426 Next, let's save the mappings 172 00:12:41.426 --> 00:12:45.176 Let's test to see if everything is working correctly now 173 00:12:47.726 --> 00:12:50.876 When you grab the right hand controller 174 00:12:50.876 --> 00:12:55.076 and squeeze the Hand Trigger or the index trigger 175 00:12:55.076 --> 00:12:58.176 you should see animations 176 00:12:58.176 --> 00:13:01.276 that simulate gripping or making a fist 177 00:13:03.976 --> 00:13:08.626 Now that we've simulated the gripping animation 178 00:13:08.626 --> 00:13:10.676 let's create an object here 179 00:13:10.676 --> 00:13:15.126 so that when we actually grasp it 180 00:13:15.126 --> 00:13:19.226 the object will appear to be held in our hand 181 00:13:19.226 --> 00:13:22.226 Let's place a table on the ground 182 00:13:22.226 --> 00:13:24.026 so it's easier to pick up objects 183 00:13:24.026 --> 00:13:27.326 then we'll place an object on top of it 184 00:13:27.326 --> 00:13:29.526 Since we have StarterContent available 185 00:13:29.526 --> 00:13:35.826 let's find a table from the Props section 186 00:13:35.826 --> 00:13:38.826 in StarterContent 187 00:13:38.826 --> 00:13:42.476 and place it here 188 00:13:46.727 --> 00:13:51.077 If the table feels too small, feel free to scale it up 189 00:13:54.427 --> 00:13:59.027 Let's place it nearby 190 00:13:59.027 --> 00:14:02.777 so we can grab it easily 191 00:14:02.777 --> 00:14:07.577 since we haven't implemented movement functionality yet 192 00:14:07.577 --> 00:14:10.127 If you feel it's a bit small 193 00:14:11.527 --> 00:14:16.527 locking the scale to about 1.2 times its current size 194 00:14:16.527 --> 00:14:21.927 will adjust all dimensions simultaneously 195 00:14:21.927 --> 00:14:28.177 Setting it to 1,2 will increase its size uniformly, making it slightly larger 196 00:14:34.877 --> 00:14:37.627 Let's place an object on top of it 197 00:14:37.627 --> 00:14:41.927 We'll create a blueprint for this object separately 198 00:14:41.927 --> 00:14:45.227 First, let's create a new Blueprint Class 199 00:14:45.227 --> 00:14:47.927 in Blueprints 200 00:14:47.927 --> 00:14:50.027 Let's create it as an Actor type 201 00:14:50.027 --> 00:14:58.977 Next, I'll create a blueprint file 202 00:14:58.977 --> 00:15:02.327 named BP_GrabObject 203 00:15:02.327 --> 00:15:05.427 Open up the file by double-clicking 204 00:15:05.427 --> 00:15:09.227 Here, let me search for 'Box' 205 00:15:12.077 --> 00:15:14.577 When you search for Box 206 00:15:14.577 --> 00:15:17.627 there's something called Box Collision 207 00:15:17.627 --> 00:15:21.027 So, you'll move this Box Collision to be the root 208 00:15:21.027 --> 00:15:23.677 making it the Root Component 209 00:15:23.677 --> 00:15:31.077 Next, I'll add a Static Mesh below it 210 00:15:33.227 --> 00:15:35.677 And in the Static Mesh details panel 211 00:15:35.677 --> 00:15:38.777 you can choose any object 212 00:15:38.777 --> 00:15:41.627 that could serve as 213 00:15:41.627 --> 00:15:43.777 the shape of the object 214 00:15:54.177 --> 00:15:57.577 Shall we place something angular? If we place something too round 215 00:15:59.027 --> 00:16:01.477 it might not fit well with the Box Collision 216 00:16:09.277 --> 00:16:14.327 Let's place a statue 217 00:16:17.477 --> 00:16:20.927 Since the color may not be very visible 218 00:16:20.927 --> 00:16:23.127 let's compile it first 219 00:16:23.127 --> 00:16:25.177 When you compile, the materials will appear, right? 220 00:16:25.177 --> 00:16:29.327 Currently, it might be a glass material, so it may not be very visible 221 00:16:29.327 --> 00:16:37.577 Shall we change it to a more opaque color 222 00:16:37.577 --> 00:16:39.277 to make it more visible? 223 00:16:39.277 --> 00:16:42.527 That should make it more noticeable, right? 224 00:16:42.527 --> 00:16:47.727 After changing the color 225 00:16:47.727 --> 00:16:51.000 let's adjust it to fit 226 00:16:51.000 --> 00:16:56.950 somewhat within the box size like this 227 00:17:01.627 --> 00:17:06.377 And compile, save. Since we need to handle collision later 228 00:17:06.377 --> 00:17:11.927 for the Box - Static Mesh of this object 229 00:17:11.927 --> 00:17:16.177 let's change the Collision Preset to No Collision 230 00:17:16.177 --> 00:17:20.777 so that the Static Mesh itself doesn't have collision 231 00:17:20.777 --> 00:17:25.427 We'll set it up so that only the box has collision applied 232 00:17:25.427 --> 00:17:32.277 So, let's customize 233 00:17:36.227 --> 00:17:38.077 the collision settings in the box 234 00:17:38.077 --> 00:17:39.927 Let's customize it 235 00:17:39.927 --> 00:17:42.177 so we can cut it as we please 236 00:17:42.177 --> 00:17:48.127 For the Object Type, let's set it to World Dynamic 237 00:17:48.127 --> 00:17:53.427 Next, let's change Collision Enabled 238 00:17:53.427 --> 00:17:57.877 to Query and Physics 239 00:17:57.877 --> 00:18:00.477 Let's set everything to block 240 00:18:00.477 --> 00:18:03.327 so that it blocks everything like this 241 00:18:03.327 --> 00:18:05.377 If you check the "Block" above 242 00:18:05.377 --> 00:18:07.277 it will change everything uniformly to "Block" 243 00:18:07.277 --> 00:18:10.277 So, we'll set it to "Block" for all channels 244 00:18:10.277 --> 00:18:12.277 ensuring that 245 00:18:12.277 --> 00:18:15.327 physically nothing can pass through 246 00:18:15.327 --> 00:18:18.577 Next, for this object 247 00:18:18.577 --> 00:18:20.127 we'll enable "Simulate Physics" 248 00:18:20.127 --> 00:18:22.977 so that it can fall under gravity 249 00:18:22.977 --> 00:18:26.027 and not float in the air 250 00:18:26.027 --> 00:18:28.927 Turn on "Simulate Physics" for it 251 00:18:28.927 --> 00:18:32.627 Then compile and save it 252 00:18:32.627 --> 00:18:35.577 And now let's go back to the map 253 00:18:35.577 --> 00:18:38.677 and place the Grab Object 254 00:18:38.677 --> 00:18:40.827 on top of the table 255 00:18:42.677 --> 00:18:46.077 The size seems quite large. Should we resize it smaller? 256 00:18:46.077 --> 00:18:52.479 Reducing it to about half its size should be fine 257 00:18:52.479 --> 00:18:55.727 Reducing it to 0.5 times its current size will still make it quite large 258 00:18:55.727 --> 00:18:59.477 so let's press the End key on the keyboard 259 00:18:59.477 --> 00:19:02.977 to snap it neatly to the floor 260 00:19:02.977 --> 00:19:04.977 Just to be safe 261 00:19:04.977 --> 00:19:07.827 let's place one more next to it like this 262 00:19:07.827 --> 00:19:13.077 You know you can hold down the Alt key and drag to duplicate, right? 263 00:19:13.077 --> 00:19:15.127 So, I'll place these two 264 00:19:15.127 --> 00:19:17.877 on the table like this 265 00:19:17.877 --> 00:19:23.427 And for the Table Actor 266 00:19:27.877 --> 00:19:30.977 since its collision settings are probably default 267 00:19:30.977 --> 00:19:34.427 I'll customize it to set the Object Type 268 00:19:34.427 --> 00:19:37.127 to World Static 269 00:19:37.127 --> 00:19:39.977 and leave it as it is 270 00:19:39.977 --> 00:19:43.227 For the moving objects here 271 00:19:43.227 --> 00:19:45.977 set them to World Dynamic 272 00:19:45.977 --> 00:19:48.627 and for the fixed table, set it to World Static 273 00:19:48.627 --> 00:19:53.327 So, to determine when 274 00:19:53.327 --> 00:19:56.327 the player has grabbed an object 275 00:19:56.327 --> 00:19:59.677 we'll add an event here 276 00:19:59.677 --> 00:20:06.577 IA_HandTrigger will be for functionality, not animation 277 00:20:06.577 --> 00:20:08.427 so we'll use True and False values 278 00:20:08.427 --> 00:20:12.177 So, we'll create an Enhanced Input Action for IA_HandTrigger_Right 279 00:20:12.177 --> 00:20:15.977 using True and False values 280 00:20:15.977 --> 00:20:20.227 Next, we'll check 281 00:20:20.227 --> 00:20:22.327 when the button is pressed 282 00:20:22.327 --> 00:20:25.477 We'll check when the button is pressed (Started) 283 00:20:25.477 --> 00:20:28.227 to see what objects are around our hand 284 00:20:28.227 --> 00:20:31.677 at that moment 285 00:20:31.677 --> 00:20:36.377 In this case, we'll use an Overlap check 286 00:20:38.827 --> 00:20:44.327 Since we're checking around the hand, we can use a Sphere Overlap 287 00:20:44.327 --> 00:20:50.577 We'll search 288 00:20:50.577 --> 00:20:51.977 for Sphere Overlap Actors 289 00:20:51.977 --> 00:20:56.277 This function searches 290 00:20:56.277 --> 00:20:58.777 within a specified radius, measured in centimeters 291 00:20:58.777 --> 00:21:04.427 from the position you define, within a single frame 292 00:21:04.427 --> 00:21:07.027 So, what will the reference point be? 293 00:21:07.027 --> 00:21:12.027 The reference point will be the position of the right hand 294 00:21:12.027 --> 00:21:14.277 You can use either the Right Motion Controller 295 00:21:14.277 --> 00:21:17.127 or the Right Hand for this 296 00:21:17.127 --> 00:21:18.977 Most likely, they should be nearly identical in position 297 00:21:18.977 --> 00:21:22.227 because the location value for the hand is 298 00:21:22.227 --> 00:21:24.127 relative with coordinates set to 0, 0, 0 299 00:21:24.127 --> 00:21:26.577 it aligns with the parent's position 300 00:21:26.577 --> 00:21:30.127 We'll use the Right Motion Controller as the reference point for the parent 301 00:21:30.127 --> 00:21:34.627 We're going to use 302 00:21:34.627 --> 00:21:38.327 Get World Location 303 00:21:38.327 --> 00:21:40.177 for the Right Motion Controller 304 00:21:40.177 --> 00:21:42.477 to get its location in the world 305 00:21:42.477 --> 00:21:48.527 So, w're going to use the World Location 306 00:21:48.527 --> 00:21:55.227 to search around the hand 307 00:21:55.227 --> 00:21:58.727 with a radius of about 15cm 308 00:21:58.727 --> 00:22:02.959 15cm is quite a reasonable radius for detecting objects around the hand 309 00:22:02.959 --> 00:22:06.809 Given the slight differences between VR and the real world 310 00:22:06.809 --> 00:22:09.609 a bit of extra radius like 15cm should indeed help ensure 311 00:22:09.609 --> 00:22:12.777 comfortable interaction without feeling too restrictive 312 00:22:12.777 --> 00:22:16.677 I'll search around the hand 313 00:22:16.677 --> 00:22:20.127 within a radius of about 15cm 314 00:22:20.127 --> 00:22:22.127 Then we need to specify 315 00:22:22.127 --> 00:22:25.277 which actors to search for by checking the Object Type 316 00:22:26.277 --> 00:22:31.327 So, since it's in array format 317 00:22:31.327 --> 00:22:33.777 let's use 'Make Array' to create an array 318 00:22:33.777 --> 00:22:37.528 If you connect the array values to Object Type 319 00:22:37.528 --> 00:22:40.328 you'll be able to choose the Object Type 320 00:22:40.328 --> 00:22:42.978 Here, for the object like the Statue we intended to grab earlier 321 00:22:42.978 --> 00:22:47.728 it was set to World Dynamic 322 00:22:47.728 --> 00:22:50.778 So we'll check only for the World Dynamic type here 323 00:22:50.778 --> 00:22:54.328 Next, for Ignore Actors 324 00:22:54.328 --> 00:22:55.928 actors to ignore in collision checks 325 00:22:55.928 --> 00:22:59.128 we shouldn't check against ourselves 326 00:22:59.128 --> 00:23:06.478 So similarly, we will create an Array 327 00:23:06.478 --> 00:23:11.578 and pass the Array values here 328 00:23:11.578 --> 00:23:14.278 The actor that shouldn't collide is itself 329 00:23:14.278 --> 00:23:18.978 So, we'll get a reference to self 330 00:23:18.978 --> 00:23:23.229 put information about itself into the array 331 00:23:23.229 --> 00:23:26.028 to not collide itself 332 00:23:26.028 --> 00:23:29.328 I will register it as an Ignore Actor 333 00:23:34.978 --> 00:23:38.278 The Dynamic actors might not be limited to 334 00:23:38.278 --> 00:23:40.778 just the Grab Object we just created 335 00:23:40.778 --> 00:23:45.378 So just in case, we'll use a class filter 336 00:23:45.378 --> 00:23:49.678 to ensure only BP_GrabObject is checked 337 00:23:49.678 --> 00:23:52.178 Even if they are dynamic 338 00:23:52.178 --> 00:23:57.028 we'll only check those that are of the BP_GrabObject type 339 00:23:59.378 --> 00:24:03.478 Then, anyway, the result will be multiple arrays 340 00:24:03.478 --> 00:24:06.328 We will take the first one among them 341 00:24:06.328 --> 00:24:10.128 So, we'll use Get to fetch the 0th element 342 00:24:10.128 --> 00:24:13.678 which is the first one that was touched in the array 343 00:24:14.978 --> 00:24:19.678 For the retrieved entity, physics are currently enabled, right? 344 00:24:19.678 --> 00:24:21.528 So, gravity is applied 345 00:24:21.528 --> 00:24:24.078 and when we grab manually 346 00:24:24.078 --> 00:24:26.978 the object falls down due to gravity, making it hard to hold onto 347 00:24:26.978 --> 00:24:30.028 We'll need to disable physics first 348 00:24:30.028 --> 00:24:31.678 so casting should be done beforehand 349 00:24:31.678 --> 00:24:38.128 First, cast to BP_GrabObject 350 00:24:41.778 --> 00:24:49.178 We'll set the Simulate Physics of the Box Component 351 00:24:49.178 --> 00:25:01.378 from the object to false 352 00:25:01.378 --> 00:25:04.028 turning it off 353 00:25:04.028 --> 00:25:05.778 If it's checked it means it's turned on (True) 354 00:25:05.778 --> 00:25:08.578 and if it's unchecked, it means it's turned off (False) 355 00:25:09.378 --> 00:25:12.078 We'll turn off physics first 356 00:25:12.078 --> 00:25:14.328 then attach it to my hand's position 357 00:25:14.328 --> 00:25:16.928 We'll attach it to the Right Hand 358 00:25:16.928 --> 00:25:27.328 So, we'll use Attach To Component for this object 359 00:25:27.328 --> 00:25:29.828 and our hand is the Component 360 00:25:29.828 --> 00:25:33.628 Since it's a Skeletal Mesh Component 361 00:25:33.628 --> 00:25:35.878 we'll attach it to the Component 362 00:25:37.228 --> 00:25:40.878 To organize it neatly 363 00:25:43.028 --> 00:25:49.928 I'll create a reroute node and double-click to make the connection look tidy like this 364 00:26:00.528 --> 00:26:05.128 When attaching, there's a rule involved 365 00:26:05.128 --> 00:26:09.928 This rule includes three options: Keep Relative 366 00:26:09.928 --> 00:26:13.878 Keep World, and Snap to Target 367 00:26:14.228 --> 00:26:17.928 The "Snap to Target" option means that when grabbed 368 00:26:17.928 --> 00:26:20.178 it moves to exactly match the position of my hand 369 00:26:20.178 --> 00:26:23.528 aligning precisely with it 370 00:26:23.528 --> 00:26:27.128 "Keep World" or "Keep Relative" means that when grabbed, it maintains its position relative to the world 371 00:26:27.128 --> 00:26:30.078 or relative to its parent 372 00:26:30.078 --> 00:26:32.478 while being attached 373 00:26:32.478 --> 00:26:35.328 at the moment it's grabbed 374 00:26:35.328 --> 00:26:38.378 Since it's a bit tricky to explain verbally 375 00:26:38.378 --> 00:26:40.978 I'll set all of these to 376 00:26:40.978 --> 00:26:44.378 "Keep World" for now 377 00:26:46.128 --> 00:26:49.728 Next, we'll attach it 378 00:26:49.728 --> 00:26:51.078 to my hand 379 00:26:51.078 --> 00:26:55.728 So, we'll fetch the Right Hand 380 00:26:55.728 --> 00:27:01.628 and set it as the Parent for the attachment 381 00:27:01.628 --> 00:27:06.078 So, I'll compile and save to attach it to the hand 382 00:27:07.278 --> 00:27:21.578 Then let's play again to see how it works 383 00:27:21.578 --> 00:27:24.728 It seems to be located below 384 00:27:24.728 --> 00:27:27.878 Anyway, what happens when you grab it like this? 385 00:27:27.878 --> 00:27:29.178 When you grab it now 386 00:27:29.178 --> 00:27:32.028 it should attach precisely to your hand 387 00:27:32.028 --> 00:27:33.528 at the position where you grabbed it 388 00:27:33.528 --> 00:27:37.228 You've confirmed that when you grab it, it attaches to your hand like this 389 00:27:37.228 --> 00:27:41.028 although you haven't made the release action yet 390 00:27:41.028 --> 00:27:45.028 Implementing object grabbing functionality 391 00:27:45.028 --> 00:27:48.628 But what happens to us when it attaches like this? 392 00:27:48.628 --> 00:27:51.228 It might feel a bit awkward, right? 393 00:27:51.228 --> 00:27:55.328 If we want to specify a precise grab point 394 00:27:55.328 --> 00:27:57.678 and have it attach exactly there 395 00:27:57.678 --> 00:28:00.378 we should change the Location Rule 396 00:28:01.778 --> 00:28:06.328 from Keep 397 00:28:06.328 --> 00:28:10.428 to Snap to Target 398 00:28:10.428 --> 00:28:13.278 instead of Keep World 399 00:28:13.278 --> 00:28:16.178 Rotation should also be set to Snap to Target 400 00:28:16.178 --> 00:28:20.178 There's no need to change Scale 401 00:28:20.178 --> 00:28:23.128 There's no need to adjust it to fit the size of the hand, just the statue 402 00:28:23.128 --> 00:28:25.228 Let's ignore scaling 403 00:28:25.228 --> 00:28:29.228 and just align the position and rotation according to the hand's direction 404 00:28:29.228 --> 00:28:33.328 I'll go ahead and compile and save these changes 405 00:28:35.528 --> 00:28:37.628 Let's test it again to see how it behaves now 406 00:28:42.578 --> 00:28:46.978 I've grabbed it Now, when I grab it 407 00:28:46.978 --> 00:28:51.028 does it attach exactly to the position of my hand like this? 408 00:28:51.028 --> 00:28:54.478 But it seems like the position isn't quite what we wanted 409 00:28:54.478 --> 00:28:57.028 So, now we can use a Socket 410 00:28:57.028 --> 00:29:03.178 as the Grab Point 411 00:29:04.428 --> 00:29:08.278 If you look at the viewport, I'll show you the Right Hand 412 00:29:08.278 --> 00:29:12.430 If you look at the Right Hand 413 00:29:12.430 --> 00:29:15.478 you'll see that currently the pivot is around the wrist area 414 00:29:15.478 --> 00:29:19.478 So, when the statue snapped to attach 415 00:29:19.478 --> 00:29:21.828 it ended up attaching at this wrist position where the pivot is currently located 416 00:29:21.828 --> 00:29:24.028 So, earlier it looked a bit odd because of that 417 00:29:24.028 --> 00:29:28.778 So, you would typically want it to attach 418 00:29:28.778 --> 00:29:30.228 around the palm area instead 419 00:29:30.228 --> 00:29:35.078 To align it around the palm area 420 00:29:35.078 --> 00:29:38.128 you can specify the attachment point on the palm using something called a Socket 421 00:29:38.128 --> 00:29:43.478 To go to the location 422 00:29:43.478 --> 00:29:45.478 where the original file SKM_MannyXR_right for Right Hand is located 423 00:29:45.478 --> 00:29:49.778 If you click on the folder icon below 424 00:29:49.778 --> 00:29:52.478 you'll see the original location where it's located 425 00:29:52.478 --> 00:29:54.719 It's located in the Characters - Meshes folder 426 00:29:54.719 --> 00:29:59.328 Please double-click to open this file 427 00:30:03.328 --> 00:30:05.778 Please click on the skeletal icon at the top 428 00:30:05.778 --> 00:30:09.178 the skull icon 429 00:30:09.178 --> 00:30:11.928 So 430 00:30:16.178 --> 00:30:20.828 right-click 431 00:30:20.828 --> 00:30:23.378 below the root and 432 00:30:25.078 --> 00:30:26.828 add a Socket 433 00:30:26.828 --> 00:30:29.128 to create a new socket there 434 00:30:29.128 --> 00:30:32.578 In the Details panel 435 00:30:35.178 --> 00:30:41.128 I'll name the socket "GrabPoint" and position it where we want it to be 436 00:30:43.928 --> 00:30:52.678 Now, with the GrabPoint selected 437 00:30:52.678 --> 00:30:58.728 I'll move it to align around the center of the hand, like this 438 00:30:59.628 --> 00:31:04.428 This looks about right 439 00:31:09.978 --> 00:31:13.778 If it's centered on the hand and facing upwards in the front direction 440 00:31:13.778 --> 00:31:18.428 the statue should be grabbed like this 441 00:31:18.428 --> 00:31:21.928 So, to match the shape of the hand 442 00:31:21.928 --> 00:31:26.278 we need to rotate it so that the front direction 443 00:31:26.278 --> 00:31:36.729 points towards the front of the hand 444 00:31:36.729 --> 00:31:39.479 If you feel confused at any point 445 00:31:39.479 --> 00:31:42.379 you can attach a preview here to help visualize it beforehand 446 00:31:42.379 --> 00:31:45.379 You can add a preview asset here 447 00:31:45.379 --> 00:31:49.879 by clicking on "Add Preview Asset" 448 00:31:49.879 --> 00:31:51.579 and attaching the statue here as a mock-up 449 00:31:51.579 --> 00:31:53.529 The size might be a bit large 450 00:31:55.429 --> 00:31:58.829 but you can adjust it to match the shape and orientation of the hand 451 00:31:58.829 --> 00:32:02.679 So, with this orientation 452 00:32:02.679 --> 00:32:05.479 we should adjust the Grab Point slightly downward, right? 453 00:32:05.479 --> 00:32:09.029 We should lower it slightly 454 00:32:09.029 --> 00:32:12.329 so that it aligns like this when grabbed 455 00:32:12.329 --> 00:32:13.929 considering that we actually reduced the size by half (0.5 scale) 456 00:32:13.929 --> 00:32:16.529 and adjusted accordingly 457 00:32:16.529 --> 00:32:19.129 I'll set the socket position 458 00:32:19.129 --> 00:32:23.579 like this for attachment 459 00:32:24.779 --> 00:32:30.779 save the rotation and position 460 00:32:30.779 --> 00:32:33.529 and copy the name "Grab Point" with Ctrl + C for the socket 461 00:32:33.529 --> 00:32:36.029 To make it easier 462 00:32:36.029 --> 00:32:38.579 let's go back to the Blueprint settings 463 00:32:38.579 --> 00:32:40.779 and in the Event Graph 464 00:32:40.779 --> 00:32:46.079 use Attach Actor To Component again 465 00:32:46.079 --> 00:32:49.979 but this time specify the socket name directly 466 00:32:49.979 --> 00:32:53.479 So, we'll specify the socket name as "GrabPoint" when attaching it 467 00:32:53.479 --> 00:32:56.629 directly telling it to attach there 468 00:32:56.629 --> 00:33:00.179 Attach to the Grab Point socket on the Right Hand 469 00:33:00.179 --> 00:33:04.279 using Snap for both location and rotation 470 00:33:04.279 --> 00:33:06.329 We won't apply scaling 471 00:33:06.329 --> 00:33:08.679 We'll maintain the scale 472 00:33:08.679 --> 00:33:11.079 as it originally was for the object 473 00:33:12.529 --> 00:33:18.529 I'll compile, save, and then let's test grabbing it again 474 00:33:26.529 --> 00:33:29.679 How does it feel picking it up again now? 475 00:33:29.679 --> 00:33:33.279 Now it has become like this, fitting to my hand 476 00:33:33.279 --> 00:33:35.429 But it's a bit too high up, right? 477 00:33:35.429 --> 00:33:38.979 Because we lowered the statue a bit 478 00:33:38.979 --> 00:33:43.079 I think it would fit better if we raise it a bit 479 00:33:43.079 --> 00:33:48.679 So earlier, we lowered it from the hand socket 480 00:33:48.679 --> 00:33:51.329 but I'll try raising it a bit 481 00:33:51.329 --> 00:33:55.479 Shall we raise it about this much? 482 00:33:59.629 --> 00:34:01.279 Then, how about holding it like this again? 483 00:34:01.279 --> 00:34:06.429 Now it feels like we're really holding the statue 484 00:34:08.079 --> 00:34:12.079 Implementing the object placement function 485 00:34:12.579 --> 00:34:18.479 Now that we've grasped it, let's try placing it down once 486 00:34:18.479 --> 00:34:21.279 It's very easy to place it down 487 00:34:21.279 --> 00:34:24.129 When is the right time to put it down? 488 00:34:24.129 --> 00:34:29.279 When we've completed it, that's when we'll put it down, right? 489 00:34:35.179 --> 00:34:39.279 Use "Detach From Actor" to 490 00:34:39.279 --> 00:34:44.129 If you use "Detach From Actor," 491 00:34:44.129 --> 00:34:47.729 you'll be able to detach what's currently attached 492 00:34:47.729 --> 00:34:50.079 When you detach something using "Detach From Actor," 493 00:34:50.079 --> 00:34:51.779 you can detach what's currently attached 494 00:34:51.779 --> 00:34:54.179 However, if you haven't saved or stored what you're currently holding 495 00:34:54.179 --> 00:34:58.129 you won't be able to detach it because the system doesn't remember what you were holding at that moment 496 00:34:58.129 --> 00:35:02.379 So, when you attach something here 497 00:35:02.379 --> 00:35:06.779 you'll save this attached actor to a variable 498 00:35:06.779 --> 00:35:09.779 You'll create a variable 499 00:35:11.979 --> 00:35:21.020 and name it something like "Current Grabbed Actor," 500 00:35:21.020 --> 00:35:24.970 of type "BP Grab Object," 501 00:35:24.970 --> 00:35:29.579 to store the actor you're currently holding 502 00:35:29.579 --> 00:35:31.929 And you'll select the actual object reference 503 00:35:31.929 --> 00:35:37.679 the Grab Object, for its Object Reference 504 00:35:37.679 --> 00:35:42.379 Compile and save to ensure the variable is compiled properly 505 00:35:42.379 --> 00:35:46.179 Then you'll set this variable 506 00:35:50.279 --> 00:35:52.229 When you set it 507 00:35:52.229 --> 00:35:55.279 you'll tidy up this Grabbed Actor 508 00:35:59.379 --> 00:36:01.229 a bit beforehand 509 00:36:02.979 --> 00:36:07.879 We're going to save 510 00:36:07.879 --> 00:36:10.129 the currently attached actor 511 00:36:10.129 --> 00:36:11.729 into the Current Grabbed Actor variable 512 00:36:11.729 --> 00:36:14.029 Then, when you grab an object 513 00:36:14.029 --> 00:36:16.879 the actual object you're holding will be stored in this variable, right? 514 00:36:16.879 --> 00:36:23.929 So, when you release it 515 00:36:23.929 --> 00:36:27.829 you'll retrieve it from Current Grabbed Actor and detach that actor 516 00:36:27.829 --> 00:36:31.029 When releasing it 517 00:36:31.029 --> 00:36:39.229 you'll detach it from its current position 518 00:36:39.229 --> 00:36:41.379 keeping it in the world coordinate system (Keep World) 519 00:36:41.379 --> 00:36:44.629 so it drops from its current position without changing its original world coordinates 520 00:36:44.629 --> 00:36:46.579 If you just detach it without any additional actions 521 00:36:46.579 --> 00:36:48.479 it will remain suspended in the air 522 00:36:48.479 --> 00:36:51.579 Then you'll turn on physics again 523 00:36:51.579 --> 00:36:56.129 You'll set "Simulate Physics" on the box 524 00:37:03.979 --> 00:37:06.629 to turn physics simulation back on 525 00:37:08.179 --> 00:37:10.279 Compile and then save 526 00:37:12.829 --> 00:37:15.179 Should we test it out again? 527 00:37:17.520 --> 00:37:22.420 Press play, grab the object 528 00:37:22.420 --> 00:37:25.420 and now when you release it, it should drop like this 529 00:37:25.420 --> 00:37:30.479 Now you can grab and throw objects like this 530 00:37:32.479 --> 00:37:34.929 So, once you know how to grab 531 00:37:34.929 --> 00:37:38.329 releasing is very easy 532 00:37:39.779 --> 00:37:43.779 Handling exceptions 533 00:37:44.179 --> 00:37:49.779 So, leaving it like this seems too complex 534 00:37:49.779 --> 00:37:52.729 so I'll refactor this into a function 535 00:37:52.729 --> 00:37:57.179 So, let's add a function 536 00:37:57.179 --> 00:38:03.279 I'll create a function named GrabAction 537 00:38:03.279 --> 00:38:05.529 Next, I'll create a function named GrabAction 538 00:38:05.529 --> 00:38:09.079 and then I'll cut out all the actions we did 539 00:38:09.079 --> 00:38:17.279 when we started from the Event Graph with Ctrl + X 540 00:38:17.279 --> 00:38:18.929 Next, I'll paste everything we cut with Ctrl + X 541 00:38:18.929 --> 00:38:25.379 into the GrabAction function 542 00:38:25.379 --> 00:38:28.279 and connect it accordingly 543 00:38:29.479 --> 00:38:32.729 Then, return to the Event Graph 544 00:38:32.729 --> 00:38:40.929 and connect the GrabAction to the "Started" event 545 00:38:42.479 --> 00:38:45.779 Similarly, I'll create a function for releasing as well 546 00:38:45.779 --> 00:38:53.879 I'll create a function named ReleaseAction for releasing 547 00:38:53.879 --> 00:38:55.829 We had actions for 548 00:38:55.829 --> 00:38:57.629 when we completed the release in the Event Graph 549 00:38:57.629 --> 00:39:00.529 I'll cut those actions from the Event Graph with Ctrl + X 550 00:39:00.529 --> 00:39:03.179 paste them into the ReleaseAction function with Ctrl + V 551 00:39:03.179 --> 00:39:07.879 and connect the execution pin accordingly 552 00:39:07.879 --> 00:39:10.729 Then, return to the Event Graph 553 00:39:10.729 --> 00:39:14.179 and connect ReleaseAction 554 00:39:14.179 --> 00:39:16.179 to the "Completed" event 555 00:39:17.429 --> 00:39:20.179 Now it should be much cleaner and organized 556 00:39:20.179 --> 00:39:23.279 And now each functionality is neatly organized in its respective functions 557 00:39:23.279 --> 00:39:25.829 making it easier to review 558 00:39:25.829 --> 00:39:29.229 and understand each part 559 00:39:39.079 --> 00:39:41.929 Let's wrap it up here for now then 560 00:39:41.929 --> 00:39:44.679 Let's work on 561 00:39:44.679 --> 00:39:47.029 adding movement functionality next time 562 00:39:47.029 --> 00:39:50.779 Thank you for your hard work and patience throughout this long session 563 00:39:51.529 --> 00:39:54.779 I'll summarize what we've learned in this session 564 00:39:54.779 --> 00:39:58.429 First, to attach an object to a Hand Component 565 00:39:58.429 --> 00:40:02.579 you need to use the "Attach Actor To Component" function node 566 00:40:02.579 --> 00:40:05.029 It's important to note that 567 00:40:05.029 --> 00:40:08.579 this can only be done 568 00:40:08.579 --> 00:40:10.879 when the "Simulate Physics" feature of the object you're attaching is set to false 569 00:40:10.879 --> 00:40:13.729 Secondly, when searching for objects that can be grabbed around the hand in VR 570 00:40:13.729 --> 00:40:17.529 it's important to note that 571 00:40:17.529 --> 00:40:19.929 the visual information in VR may not perfectly match the actual sense of distance for a person 572 00:40:19.929 --> 00:40:21.929 Therefore 573 00:40:21.929 --> 00:40:24.229 you should define 574 00:40:24.229 --> 00:40:27.379 the detection area slightly wider than 575 00:40:27.379 --> 00:40:29.929 the actual size of the hand 576 00:40:29.929 --> 00:40:33.329 Otherwise, users might feel uncomfortable when trying to grab objects 577 00:40:33.329 --> 00:40:35.579 as the virtual representation may not align perfectly with their real-world perception of reach and distance 578 00:40:35.579 --> 00:40:38.680 Lastly, the third point we covered is 579 00:40:38.680 --> 00:40:40.480 using the Axis values of buttons like the Index Trigger or Hand Trigger 580 00:40:40.480 --> 00:40:42.680 to smoothly animate the fingers of the hand mesh in response to button inputs 581 00:40:42.680 --> 00:40:45.280 This method simplifies handling 582 00:40:45.280 --> 00:40:47.280 and was demonstrated 583 00:40:47.280 --> 00:40:49.880 through 584 00:40:49.880 --> 00:40:51.929 practical exercises 585 00:40:52.730 --> 00:40:53.230 Applying Hand Animations Preparing Input Functionality 586 00:40:53.230 --> 00:40:53.730 Create the IA_HandTrigger_Right file in the Inputs folder for handling object grabbing inputs Set the Value type to Digital (Bool) for the IA_HandTrigger_Right file 587 00:40:53.730 --> 00:40:54.230 Inputs received for passing to the Hand Animation Blueprint Create two files: IA_HandTriggerFloat_Right and IA_IndexTriggerFloat_Right 588 00:40:54.230 --> 00:40:54.730 Set the Value type to Axis1D (Float) to receive values corresponding to the degree of button press 589 00:40:54.730 --> 00:40:55.230 Implement functionality to pass input values to the hand animation Double-click on the ABP_HunetHand file to open its settings window 590 00:40:55.230 --> 00:40:55.730 In the Animation Settings window of ABP_HunetHand, navigate to the Anim Preview Editor tab located in the bottom left corner 591 00:40:55.730 --> 00:40:56.230 Find the Default variables and adjust the Pose Alpha Grasp value to any random value between 0 and 1. Then, observe the animation to see it in motion 592 00:40:56.230 --> 00:40:56.730 Adjust the Pose Alpha Index Curl value to any random value between 0 and 1 to observe the movement of the index finger in the animation 593 00:40:56.730 --> 00:40:57.380 Implementing the object grabbing functionality Creating the Grab Object 594 00:40:57.380 --> 00:40:58.080 In the Content Drawer, drag the SM_TableRound file from StarterContent - Props folder onto the viewport to place it 595 00:40:58.080 --> 00:40:58.730 Adjust the Scale value to 1.2 times to make it a comfortable height for picking up objects 596 00:40:58.730 --> 00:40:59.380 Apply gravity to the object so that it naturally falls downward when placed 597 00:40:59.380 --> 00:41:00.080 Select the Box component in the left Component panel Check (True) the Simulate Physics property in the right Details panel 598 00:41:00.080 --> 00:41:00.730 Implement the Grab function Keep World method, Snap to Target method 599 00:41:00.730 --> 00:41:01.230 Implement the drop object functionality Implement the release function 600 00:41:01.230 --> 00:41:01.730 Drag the Completed execution pin of the IA_HandTrigger_Right input event node 601 00:41:01.730 --> 00:41:02.230 and connect it to the Detach From Actor node to detach the actor from its parent component 602 00:41:02.230 --> 00:41:02.730 Specify the Current Grabbed Actor variable, which was stored when grabbing the object, to detach 603 00:41:02.730 --> 00:41:03.230 Set Location Rule, Rotation Rule, and Scale Rule all to Keep World 604 00:41:03.230 --> 00:41:03.730 Call the Simulate Physics node on the Box component of the detached actor and check the Simulate property 605 00:41:03.730 --> 00:41:04.230 Since the object has been released, clear the value of the Current Grabbed Actor variable that was storing the grabbed object 606 00:41:04.230 --> 00:41:04.730 Play the game and confirm that when releasing the right hand trigger, the object drops and flies away 607 00:41:04.730 --> 00:41:05.230 Exception handling Organizing Blueprint Node Declare functions named 'GrabAction' and 'ReleaseAction' 608 00:41:05.230 --> 00:41:05.730 Move the grab function nodes connected to the Started execution pin of the IA_HandTrigger_Right node into the implementation of the Grab Action function node 609 00:41:05.730 --> 00:41:06.230 Similarly, move the release function nodes connected to the Completed execution pin into the implementation of the Release Action function node 610 00:41:06.230 --> 00:41:06.730 Handle preventing duplicate grabs 611 00:41:06.730 --> 00:41:07.230 To prevent grabbing overlapping objects, connect an Is Valid node in the Grab Action function node to execute detection 612 00:41:07.230 --> 00:41:07.730 only when the Current Grabbed Actor variable is initially empty 613 00:41:07.730 --> 00:41:08.230 Conversely, connect an Is Valid node at the beginning of the Release Action function implementation to execute the release function 614 00:41:08.230 --> 00:41:08.730 only when there is a held object (Current Grabbed Actor)