Today’s implementation:

Hopping signal

To implement a jump, you first implement the input of the jump. The jump Signal is a Trigger Once Signal that is triggered on the spot when pressed.

public class PlayerInput : MonoBehaviour { ... Public bool jump; Public bool lastJump; // Record the last jump signal for comparison with the current jump signal. // Update is called once per frame void Update() { ... Bool newJump = input.getKey (keyJump); // So that only when the jump key is pressed will jump be set to true equivalent to GetKeyDown if (newJump! = lastJump && newJump) { jump = true; } else { jump = false; } lastJump = newJump; }}Copy the code

If the above code is cheap, you can directly use GetKeyDown to omit the if judgment. The function of the if check is to make jump true only when the jump key is pressed (not held, not released).

Jump animation application

Animator configuration is very simple, the new trigger parameter jump as a jump condition.

Animation triggers are also simple for now.

// Jump animation if(pi.jump) anim.settrigger ("jump");Copy the code

Lock Input while jumping

To make it impossible to control character rotation when jumping, we need to lock Input when jumping. Fortunately, we already implemented the soft switch for the input module (see: Player input module for Soul games). The question now is when to switch the input module on and off. We will use the animation state machine StateMachineBehaviour script to implement the control. For the StateMachineBehaviour script you can scroll down to the noteworthy section, which talks about it. Add a StateMachineBehaviour script as shown below.

The following is the code for FSMOnEnter, which calls a method called MSG by overloading OnStateEnter to send messages to the parent object and all of its Monobehaviors when the animation state machine reaches the animation state where the script is mounted.

using System.Collections; using System.Collections.Generic; using UnityEngine; // Use SendMessage to call animator at OnStateEnter. Other methods on gameObject public class FSMOnEnter: StateMachineBehaviour { public string[] onEnterMessage; // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { foreach (var msg in onEnterMessage) { //animator.gameObject.SendMessage(msg); animator.gameObject.SendMessageUpwards(msg); }}}Copy the code

The idea is that at the start of the jump state, the system calls the OnStateEnter method and sends a message to the gameObject of the animator to call the other script’s method OnJumpEnter, and then closes the input module with OnJumpEnter. Because StateMachineBehaviour scripts do as few things as possible, otherwise it’s hard to find problems.

public class PlayerController : MonoBehaviour { // ... Public void OnJumpEnter() {// Turn off the input module pi.inputenabled = false; }}Copy the code

Similarly, when the jump state ends, the system calls OnStateExit to send a message and turn on the input module. Also let’s make a StateMachineBehaviour script FSMOnExit. The structure is the same as FSMOnEnter. Just reload the OnStateExit method instead.

using System.Collections; using System.Collections.Generic; using UnityEngine; // Use SendMessage to call animator at OnStateExit. Other methods on gameObject public class FSMOnExit: StateMachineBehaviour {// List of methods to call public string[] onExitMessage; // OnStateExit is called when a transition ends and the state machine finishes evaluating this state override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, Int layerIndex) {/ / for each method call to send information they foreach (var MSG in onExitMessage) {/ / animator. GameObject. SendMessage (MSG); animator.gameObject.SendMessageUpwards(msg); }}}Copy the code

Also define the method OnJumpExit in the PlayerController.

public class PlayerController : MonoBehaviour { // ... Public void OnJumpExit() {// Open input module pi.inputenabled = true; // Open input module pi.inputenabled = true; }}Copy the code

After the input module is closed, our displacement is terminated, because our soft switch is achieved by setting the input to 0. In order to ensure the original horizontal displacement when jumping, we need to lock the horizontal displacement when jumping, that is, no new displacement is calculated.

public class PlayerController : MonoBehaviour { // ... Private Vector3 planarVec; Movingplanar = false private bool lockPlanar = false; // Update is called once per frame void Update() { // ... // Calculate the velocity vector if(! LockPlanar) planarVec = pi.dirmag * model.transform.forward * walkSpeed * (pi.run? RunMultiplier: 1.0f); } // The method executed when jumping is called via SendMessage in FSMOnEnter public void OnJumpEnter() {// The input module pi.inputenabled = false; lockPlanar = true; } // The method executed when jumping is called by SendMessage in FSMOnExit public void OnJumpExit() {// Open the input module pi.inputenabled = true; lockPlanar = false; }}Copy the code

In this way, the value of planarVec at the start of the jump will remain the same as the value of the previous frame, and the new value will not be computed until the end of the jump.

Jumping impulse

In order for a character to actually jump when he jumps, we need to give him an upward momentum.

public class PlayerController : MonoBehaviour { // ... // Jump speed public float jumpVelocity = 5.0f; // The character's jump impulse private Vector3 thrustVec; Rigidbody. position += planarVec * Time. FixedDeltaTime; rigidBody. position += planarVec * Time. rigidbody.velocity += thrustVec; thrustVec = Vector3.zero; } // The method executed when jumping is called by SendMessage in FSMOnEnter public void OnJumpEnter() { Y = jumpVelocity; // Calculate thrustvec. y = jumpVelocity; }}Copy the code