Welcome back to another unity VR tutorial. Last time, we talked about how to animate your hands.
And you might have noticed that you can just phase through walls and tables, objects, anything.
And that's a little bit of a problem for most VR games. So this time, we're going to talk about how
to physicalize your hands so they don't go through walls, tables, chairs, it will continuously track
your VR controller, but the hand is going to be a completely separate object that is trying to get
to the controller position using physics. Instead of just teleporting there. Every single update,
I'm going to show you guys how to do it, code and everything. So let's jump into it. I'm starting
where we left off from the last hand animation tutorial. And we're just going to go from here,
add the physics and do all the things we need to do, that video will be linked on the screen right
now. So you can go and have a look at it and get up to where we are right now. First things first,
let's fix a setting. So we're gonna go into Edit Project Settings, and then we're gonna go to time,
and this is default 2.02. But the best results are one over 61 over 90. So I'm going to change
mine to one over 90, hit enter, and it'll auto adjust. This just increases the refresh rate
of when physics are checked for next class time, we added the hands inside of the XR
rig. And we actually don't want them to be there anymore, we want to create a new game object,
we're going to call this one player, then we're going to need to unpack the XR rigs,
right click on it, go to prefab and then click on unpack and this will let us take out the left hand
and the right hand and put those inside of our player game object. As of this point, you just
have to empty hand prefabs laying on the ground. They're not useful, they're not going to move
anything. So we want these hands to interact with the world. And in order to do that, we're going to
need to add some colliders, it's going to be up to you how many clusters you want, you can have just
one box here on the palm. But the way I'm going to do it is I'm going to put one box collider here
on the palm, and then I'm going to put a bunch of capsule colliders on every single joint inside
of the finger, each one of those needs to be anchored to the correct spot inside of the hand
skeleton. That way, when you animate the hand, the movement of the hand will actually move the
colliders and therefore move your physics object and then therefore your physics will always be
accurate with the hand instead of just colliding into fingers that aren't there anymore. First,
I find the root hand at the wrist. And then I'm going to add a component and this one's going to
be a box collider. And it's going to start out super big, so we're going to make it smaller.
There we go. That's the collider for the poem, you can get as precise with this as you would like.
Now let's move on to the finger joints, you can add these box colliders to every single
joint like on the skeleton joint. But the issue with that is you cannot rotate the
box or any collider there's a position and a size, but you can't rotate the position. So
we're going to run into issues with that later if we try to add these on onto the fingers. So let's
remove this component, what we actually need to do is create a new game object and we're just
going to call this poem collider. Make sure that transform is set to zero. And then let's add a
box collider. Now instead of having to position or rotate your collider inside of this little editor,
you can just move the arrows and it's parented to whatever object that you
parented it to, so it's much easier to control. So let's do the index finger. And I'm just
going to rename these so they match kind of the naming style of everything else in this object.
And you're going to want to overlap the colliders a little bit. So make sure this little round
bit gets into the knuckle and then when we create another one that will overlap
with the other collider. Now to speed this up a little bit. After you've made your
first capsule collider, you can just duplicate it and then add it on to the next digit.
And this is what your final result will look like with all the mesh colliders. Now I've gone
through and renamed each one to correspond with the digit and bone that it relates to and that
it goes under. So now I can just hold down Ctrl and click on each of these sliders that we made
and then Ctrl C to copy and then the right hand we can enable that. Now a little trick to get all of
those colliders on the right hand because we don't want to go through the whole thing again is in the
right hand. We had flipped it using the scale so we're going to actually flip it back. So set the
scale back to one Z back to positive 90. We can paste all of the into the hand. And now we just
use the Move Tool to line all of this up. There we go. And with that all lined up,
we can go back into the hand and flip that back to negative and negative, and then just go through
and parent these to the correct bones that they belong to. And tada, there we go having both
hands using collision, one more step is with left hand and right hand selected, let's add
a rigid body. And we're not going to use gravity interpolation is going to be set to interpolate
and collision detection is going to be continuous and the mass we're going to want to increase to
something like 20 s just to give it a little weight. And so we have the ability to actually
pick up things and hold them as they'll help us get the feel of a heavy object. And we might
increase or decrease drag and angular drag just to get the right feel for hands. Sometimes I've
noticed that the rotation is a little slow. And that could be due to Angular drag. But
we'll figure that out after we get to it. Now let's re enable everything
and go back into the controllers because I want to remove all of this array interaction stuff, and
we're going to add a direct interact er and the direct interactor requires some kind of collision.
So we're going to add a sphere collider and scale this down to let's go with point five is pretty
good. Now anything in this sphere will be able to pick up so instead of the direct interactor,
where we have to re interact or where we point at something and it comes to us now we're going to be
able to pick things up based off of whatever's in this sphere. I'm going to copy this and put it on
the right hand controller as well. And of course, you'll want to flip the X axis. And now for sanity
sake, please make a prefab of your player and make a prefab of your XR rig so that these are
saved and you don't have to worry about something getting messed up. Or if you mess something up,
you can always go in and revert it by going to overrides. And you can click Revert if you make
a change. And you don't want to do that change one more thing, make sure the sphere colliders
are both set to is trigger, we want to trigger the direct interactor. So make sure these are set to
is trigger. I think we're about ready to do some coding. Now. Let's go into our scripts and our
hand script that we had from before. All of this code that you're seeing now was from the previous
video where we did all the animation. And just to specify that I'm going to write a comment
that says all of these are animation variables. And some of them if you've watched the last video
maybe a little bit different, I've gone through and changed the variable names and optimized
it a little bit. And I just realized that this speed also needs to be animation speed,
because we're going to have velocity, speed and rotation speed in a minute.
So inside of this update method, we're going to want to do a physics move, create a new method,
and inside of physics move, we want to update the position and the rotation.
So let's make a few variables, we're going to want a follow object which is going to end up being the
controller. We're anyday follow speed, and then a rotation speed. And these we're going to preset,
this one's going to be 30 ish, and this one is going to be about 100. Next, we're going to want
a transform, which is going to be a follow target. And we're also going to want a reference to the
rigidbody. And in the start method, we're going to want to do a few things. First off, we're going to
want to set the follow target. And that's going to be equal to the follow object dot transform,
we want to get a reference to the rigid body. And then I'm going to go ahead and set those
drop down values that we already set in the inspector in here just in case anything changes,
this will reset it every time we start the collision detection mode is going to be continuous
interpolation is going to be interpolate, and the mass is going to be equal to something like 20.
And then one more thing in the start method, we're going to want to automatically teleport the hands
to wherever the controllers are, when we start, we don't want it to be awkward the far away and
then just kind of your hands just zoom in from the distance. We don't want your hands to just
be there when you start. And that's pretty easy. We just set the rigid body position and rotation
to the follow target position and rotation. Okay, we're all set up. Now let's actually move the hand
while the game is running. So inside of the update method, we're going to want to add a physics move
method and inside of here we're going to want to set the position and the rotation. The position
is relatively simple. We're going to want to get a distance of how far away the hand is
in a vector and then use that vector to set the velocity and and use our speed and whatnot to
make that an accurate representation of how fast your hand is moving. So we'll make a new
variable distance. And this is going to be equal to vector three dot distance between
the follow target position and the current hand position, which will be transformed,
we're going to use this distance to apply a vector to the body.
And that is going to be the follow target position minus the Transform Position normalized times
a follow speed times the distance that we just calculated in my editor saying that it wants to
fix the order of operations for this. So it just puts these two in parenthesis. And we
can actually test this out right now, make sure to save your work. And let's open unity up, make sure
everything else is enabled, don't forget to set the hands new variables that we have.
So this follow object for the left hand is going to be the left hand controller,
and then the right hand controllers follow object is going to be the right hand controller. And
let's see if that works. The physics works. I can move this cube around with my hand.
But I can't control the rotation positions fine. Feels good. But when I rotate my hand,
obviously, nothing happens. So let's fix rotation. Now, it's good to check your progress every so
often get in the game, play it play, play your changes, make sure you didn't break anything,
because super annoying to write a huge chunk of code and then go in and test and it's not
working. And now you have to go back and figure out what did you do in the last four hours that
broke it where as opposed to if you test it every 10 or 30 minutes, you don't have to go back and
look through as much code every kind of major milestone you hit, just go back in and check
and see if it works as expected. So now let's do rotation, I want to be totally honest here,
rotation quaternions. Their magic, it's wizardry. So I scoured the internet and found some info on
Reddit and found some info on Google. And this is the code that I came up with to actually get
the rotation to work physics based. First, we're going to need a variable
and we're going to call this one Q, because it's going to be a quaternion. And it's going to be the
follow target dot rotation times the quaternion inverse of the body rotation. So this essentially
does what the same thing with position does, it gets the distance between the rotation of the
target and the rotation of your current hand, then we're going to convert that rotation to an angle,
how many degrees off is it so it's going to be Q two angle axis, and we're gonna type out float
angle and our vector three axis. So this gives us a flow variable of the angle and then a vector
three of the axis of rotation. And we're going to use that to set the angular velocity of the rigid
body. And this is going to be angle times axis times math F degree to read times rotate speed,
and my editor is going to want to reorder this as well. I don't know why. So all of these added
together give us a vector three of the angular velocity that we need to move the hand rigid body
to match the controller, don't ask me how I do know that this converts the degrees of 60 degrees,
it converts it to radians. So if you ever took calculus or trigonometry or I forgot what class
that was greased radians, there's some kind of conversion for that. And then this sets the speed,
I have noticed that if you set set the speed too high, it will kind of overcorrect. So if
you set the speed really high, you will also need to increase the angular drag
because it will kind of rubberband a little bit, it'll just kind of shake around. So now let's
try this. See if it works. Save, go back to Unity antenna, and you'll notice that the physics works.
I can actually just pick up the cube using physics and not even pick it up.
So you'll notice our hands are actually not lined up correctly. They're offset but you can
use physics, everything works. Okay, let's add some offsets so that our hand isn't awkwardly
turned. Let's just duplicate this a couple times change these to vector threes. And then we want a
position offset, and we want a rotation offset. And then down here, just before position, we're
going to calculate our offset and we're going to create a temporary variable called position
with offset and that's going to be equal to the follow target dot position plus
the position offset. And then everywhere we have a follow target position, we're going to replace it
with the position with offset. There we go. And then we do the same thing for rotation except
it's going to be a rotation with offset and then we have to deal with quaternions. So this is going
to be follow target rotation times, quick turn in EULAR rotation offset, and then we need to copy
the rotation with offset and replace the follow target rotation. With that, there we go. Now we
should be able to define these offsets inside of Unity flip back over. And you'll notice we
have these position and rotation offsets. So now you play and then while you're in play mode, just
adjust these and then copy the component and then when you come out of play mode, you can paste it,
you'll notice that the cube actually will move through the box sometimes, and in order to fix
that, you're going to go to the grabbable, click on the grabbable object, which is the
cube in this case, and then in movement type check velocity tracking, and that should fix that issue,
you're probably noticing that one pretty big issue and it's when you pick up things,
your hand kind of flops around, even though you're holding it, you can still rotate the object but
your hand also rotates in a weird positions. And the reason that is is because we haven't joined
the hand and the object you're holding, they're just kind of both tracking to the XR controller.
And so this is going to end up being a multi part video series of how to have realistic hands hands
are one of if not the most important aspect of any VR game. And so we're going to dedicate a
lot of time and attention to getting really good, realistic feeling hands if this video provided you
with any value please give me a like if you used any of the code or anything like that, please like
this video, it really helps me out. YouTube's algorithm recognizes it as a video you guys are
enjoying. And it really just helps the channel grow. If you have any questions about the code
that we just went over, please add that to the comments. I reply to every single comment and I
do my best to help you guys out with your personal projects and specific questions that you have. So
don't hesitate to reach out and I'll see you guys in the next video next week.