Unity 3rd Person Combat & Traversal: Implementing Jump Animation

Hello,

I’m trying to implement a Jump State machine, but when I try to play the animation it won’t work at all…
I mean it actually jump 'cause I’m using force on the RigidBody, but not the animation.
At the moment I’m just trying with hardcoded value:

stateMachine.Animator.Play("Jump_Enter", 0);

The second parameter should be the layer, If I’m not getting wrong :thinking:
Just to be more complete I’ll post the entire code here:

 public class PlayerJump : PlayerBaseState
    {
        public PlayerJump(PlayerStateMachine stateMachine) : base(stateMachine) { }

        public override void Enter()
        {
            Vector3 jumpForce = new Vector3(stateMachine.Controller.velocity.x, 12, stateMachine.Controller.velocity.z);
            stateMachine.GetComponent<Rigidbody>().isKinematic = false;
            stateMachine.GetComponent<Rigidbody>().useGravity = true;

            stateMachine.Animator.Play("Jump_Enter", 0);
            stateMachine.ForceReceiver.AddForce(jumpForce);
        }

        public override void Tick(float deltaTime)
        {
            if(stateMachine.GetComponent<Rigidbody>().velocity.y < 0.1f)
            {
                stateMachine.GetComponent<Rigidbody>().isKinematic = true;
                stateMachine.GetComponent<Rigidbody>().useGravity = false;
                stateMachine.Animator.CrossFade("Jump_Exit", 0.1f);
                stateMachine.SwitchState(new PlayerFreeLookState(stateMachine));
            }
        }

        public override void Exit()
        {
        }
    }

If the animation is not playing it could be the animation itself.
I would check the animation plays in the unity editor window as some animation may not work with the model depending on the rig settings.

Let me know on this.

I am not sure if we will be adding jump later in the course so my help may be limited in that respect

The animation is fine, so I’m making wrong something else for sure.
Maybe I should add a trigger and connect the animation to “Any State”, that would more easy

We will be implementing jump the next section so i would hold fire until then :slight_smile:

1 Like

Hey @MaximilianPs , here is one possible solution for a jump interaction. Keep in mind - this is buggy and doesn’t take into account a lot of variables

The main idea I had was to reuse our logic from the Impact State. And not use a Rigidbody. So I’ve added the following:

In the PlayerStateMachine.cs I’ve added the Jump Events like this

    private void OnEnable()
    {
        Health.OnTakeDamage += HandleTakeDamage;
        Health.OnDie += HandleDeath;
        InputReader.JumpEvent += HandleJump;
    }



    private void OnDisable()
    {
        Health.OnTakeDamage -= HandleTakeDamage;
        Health.OnDie -= HandleDeath;
        InputReader.JumpEvent -= HandleJump;
    }

   private void HandleJump()
    {
        SwitchState(new PlayerJumpState(this));
    }

I’ve also added 2 new variables there as well. A float that will hold the Vertical Velocity and a LayerMask for the ground check

public float VerticalVelocity { get; set; }
[field:SerializeField] public LayerMask GroundLayer { get; private set; }

And to finish things off I’ve made PlayerJumpState.cs like this

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerJumpState : PlayerBaseState
{
    private readonly int _jumpStartHash = Animator.StringToHash("JumpStart");

    private float _groundedTimer; 
    private float _jumpHeight = 1.2f;
    private float _gravityValue = 18f;
    private bool _groundedPlayer;
    private LayerMask _groundLayers;
    private Vector3 _movement;

    public PlayerJumpState(PlayerStateMachine stateMachine) : base(stateMachine) { }

    public override void Enter()
    {
        //if you have my Foot IK script on the player you need to disable it
        stateMachine.FeetGrounder.enabled = false;
        
        //we get the current velocity
        _movement = stateMachine.Controller.velocity;
        //we add the Jump velocity to it 
        stateMachine.VerticalVelocity += Mathf.Sqrt(_jumpHeight * 2 * _gravityValue);
        _movement.y = stateMachine.VerticalVelocity;
        
        //we trigger the jump animation - Its a single animation not jump start / middle / end 
        stateMachine.Animator.CrossFadeInFixedTime(_jumpStartHash,0.1f);
        //we apply the force with our move script
        Move(_movement,Time.deltaTime);
        Debug.Log("Entered The Jump State");
    }

    public override void Tick(float deltaTime)
    {
        //if we are on the ground and our velocity is lower than 0 - we switch back to locomotion
        if (GroundedCheck() && stateMachine.VerticalVelocity < 0f)
        {
            Debug.Log("Finished the Jump State");
            stateMachine.VerticalVelocity = 0f;
            stateMachine.FeetGrounder.enabled = true;
            ReturnToLocomotion();
        }
        //this "fakes" the gravitation pull - makes us fall to the ground
        stateMachine.VerticalVelocity -= _gravityValue * Time.deltaTime;
        Move(_movement, Time.deltaTime);
    }

    public override void Exit()
    {
        
    }

    private bool GroundedCheck()
    {
        //this is the code from the 3rd person character controller from unity.
        // set sphere position, with offset
        var position = stateMachine.transform.position;
        Vector3 spherePosition = new Vector3(position.x, position.y - 0.14f, position.z);
        _groundedPlayer = Physics.CheckSphere(spherePosition, 0.5f, stateMachine.GroundLayer,
            QueryTriggerInteraction.Ignore);
        return _groundedPlayer;
    }
}

For my Animator - I’ve added a single animation for the jump. I’ve tried with 3 (start/middle/end) but it was way too buggy

You will need to set all your ground/scene elements to a new layer (ex: environment) for the ground check to work

1 Like

Nice work there mihaivadan, It will be interesting to see what approach Nathan takes and if its the same approach :slight_smile:

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.