top of page
Writer's picturesantosh nalla

Climbing System Implementation In Unity

If you have ever played games like last of us, Uncharted, Assassins Creed you would know what i am talking about. Different games follow different climbing mechanics, be it climbing walls, building. etc.



Before you read this blog i suggest you to watch the video. When the player goes near containers and clicks "space/jump button", he jumps on the container with an animation. So how can we achieve this?

And before we talk about "how?", try to understand how unity animations work.

What is root node? The root node in a model tends to be the one where all of the other armature are attached.This is the only node that actually move or translate in your environment. If we check the box "Apply root motion", we can actually catch hold of that root node motion in animation and character can move forward without any code.

So if you are downloading the animations form mixamo or making your own animations, make sure you download those animations along with the root node motion. In Unity so that once we check "Apply root node", we don't have to translate/apply forces to our character to move. Our character moves as in those animations(root motion).

So once we check this "Apply root motion" check box, all we have to do is shift between animations and character translates as animated. This makes our job really easy for all the complex motions we see in games.




Read the below for more information on root motion:

Treadmill vs root motion: There are two types of animation, treadmill and root motion. Treadmill means that the animation stays at the origin and we use code to move that asset around. Root motion means the motion is built right into the animation and it's the animation that determines how far something moves rather than code.




Look at the image above. If you go to the animations tab of any "Humanoid" animation, you can find these options - Loop Time,Loop pose, Root Transform Rotation, Root Transform Position(Y) and Root Transform Position(XZ).

These options are mainly related to the root motion of the root node for that particular animation. Its like restricting a particular motion/rotation of that root node while we play that animation.

Root Transform Rotation: This option captures the rotation of the root node and applies it to the whole game object. You can set it to Bake Into Pose to disable the root motion rotation. With this option selected, the rotation will be treated as a visual effect of the animation and will not be applied to the game object. You should set it to true for every animation that shouldn't rotate the character. You can set the Based Upon option to one of the following options: Root Transform Position Y: This option captures the vertical movement of the root node and applies it to the whole game object. You can set it to Bake Into Pose to disable the root motion in the Y axis. With this option selected, the Y axis motion will be treated as a visual effect of the animation and will not be applied to the game object. You should set it to true for every “on ground” animation (unless it's a jump). Root Transform Position XZ : This option captures the horizontal (XZ) movement of the root node and applies it to the whole game object. You can set it to Bake Into Pose to disable the root motion in the X and Z axis. With this option selected, horizontal motion will be treated as a visual effect of the animation and will not be applied to the game object. You should set it to true for all stationary animations (such as Idle).


Loop time: by checking this you play this animation again and again. Loop Pose: will actually get rid of any forward movements that are in our animation.


For example while you play running animation, you find that your character is syncing to the ground. That means the running animation you are using is having "Y" motion which is making it to having this negative Y motion into the ground. So by checking this option -"Root Transform Position Y - Bake into Pose", you can prevent this "Y" movement.

Try to download a character and animations from Mixamo or any 3D software along with root motion and experiment with different options to loan more about these options.


Remember if these animations are Generic, you wont see these options. Now the next question comes "What is the difference between Generic and Humanoid Animations?"

The difference is that Humanoid animation can be retargeted to any kind of humanoid avatar. Even if the transform hierarchy doesn't match. While a Generic animation will only work if the destination avatar share the same transform hierarchy.

To explain the above set of lines in a much simpler way, if you are having 2 humanoid characters, you can use one humanoid animations on to the other. These animations still work because all humanoid characters are rigged in a similar way. Bone structure remains identical. (even if its not, you can re-target by just clicking on "configure" button).

But this is not the case for generic. Animations which are implied on to one generic, cannot be applied on to the other.


Now that you have understood about the root motion, lets try to achieve the climbing system in unity.

Here is how i achieved this. For every container base i have put a collider, so that only when the character stays in that collision area, it will be able to play that jump animation. Here you might get a question - "How does the character move up by just playing animation?" This is taken care by "Root Motion" of that particular animation. So all that transforms/rotations are taken case by Root Motion of that particular animation.

To actually fit in that animation we need to make some minor changes in our code like- when the animation is played, making sure the character is facing the container.... making sure the character colliders don't effect our animations etc... These minor changes can easy refine your climb system.


So here is a sample code-


    private void OnTriggerStay(Collider other)
    {
        if (other.tag == "JumpArea" && _characterState != CharacterStates.Climbing)
        {
            LedgeJumping(other.transform.eulerAngles);
        }

        if (other.tag == "HangingArea")
        {
            float _hangingMove = Input.GetAxis("Horizontal");
            _animator.SetFloat("_aHandMovement", _hangingMove);
        }
    }

    public void LedgeJumping(Vector3 _rotation)
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            transform.rotation = Quaternion.Euler(_rotation);
            _animator.SetTrigger("_aFreeHang");
            _characterState = CharacterStates.Climbing;
            _footCollider.isTrigger = true;

        }
    }




1,158 views0 comments

Recent Posts

See All

Comments


bottom of page