To make a character jump in Unity, you apply an upward force or adjust the vertical component of the character's movement vector when a jump input is detected, ensuring the character is grounded beforehand. This process varies slightly depending on whether you're using Unity's built-in CharacterController
component or a Rigidbody
for physics-based movement.
Understanding the Core Jump Mechanics
At its foundation, a jump is the application of an upward velocity to a character. In Unity, this typically means manipulating the y
component of the character's velocity vector.
- Jump Power/Height: You'll define a variable, often called
jumpPower
orjumpHeight
, which dictates the strength or height of the jump. - Velocity Adjustment: When the jump action is triggered, the character's current vertical velocity is set or incremented by this jump value. For instance, you might directly set
velocity.y
to yourjumpPower
or calculate an initial velocity based on a desiredjumpHeight
to counteract gravity.
Implementing a Jump with Unity's CharacterController
Unity's CharacterController
is designed for first and third-person player movement that is not entirely physics-driven, but still interacts with collisions. It provides robust collision detection without applying actual physics forces like momentum or torque.
1. Script and Component Setup
-
Attach Components:
- Add a
CharacterController
component to your character GameObject. - Create a new C# script (e.g.,
PlayerMovementController
) and attach it to the same GameObject.
- Add a
-
Declare Variables: In your script, define variables for movement speed, jump strength, and gravity.
using UnityEngine; using UnityEngine.InputSystem; // For the new Input System [RequireComponent(typeof(CharacterController))] public class PlayerMovementController : MonoBehaviour { private CharacterController controller; private Vector3 playerVelocity; // Stores the character's current velocity private bool isGrounded; // Checks if the character is on the ground public float playerSpeed = 5.0f; public float jumpHeight = 1.2f; // How high the character jumps public float gravity = -9.81f; // Standard gravity // For the new Input System (assign in Inspector) public PlayerInput playerInput; private InputAction jumpAction; // ... (other actions like 'Move')
2. Initialize and Grounded Check
In the Awake
or Start
method, get a reference to the CharacterController
. The Update
method is where you'll handle gravity and check if the character is touching the ground.
void Awake()
{
controller = GetComponent<CharacterController>();
if (playerInput != null)
{
jumpAction = playerInput.actions["Jump"]; // Replace "Jump" with your actual action name
// ... (initialize other actions)
}
}
void OnEnable()
{
jumpAction?.Enable();
jumpAction?.performed += OnJump; // Subscribe to the jump action event
}
void OnDisable()
{
jumpAction?.performed -= OnJump; // Unsubscribe
jumpAction?.Disable();
}
void Update()
{
isGrounded = controller.isGrounded; // Use CharacterController's built-in ground check
if (isGrounded && playerVelocity.y < 0)
{
playerVelocity.y = -2f; // Apply a small downward force to keep grounded
}
// Apply gravity constantly
playerVelocity.y += gravity * Time.deltaTime;
// Apply the total movement, including vertical velocity from gravity/jump
controller.Move(playerVelocity * Time.deltaTime);
}
For more information, refer to the Unity CharacterController Documentation.
3. Jump Input and Application
You need to detect when the player initiates a jump and, if the character is grounded, apply the upward velocity.
-
Old Input Manager (
Input.GetButtonDown
):// Inside Update() if (Input.GetButtonDown("Jump") && isGrounded) { // Set the upward velocity directly playerVelocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity); // This is equivalent to applying 'jump power' to the vertical velocity. }
-
New Unity Input System: This system provides a more flexible and event-driven approach. You connect your jump action to a method that will be called when the input is performed.
// This method is called when the "Jump" action is performed private void OnJump(InputAction.CallbackContext context) { if (isGrounded) { // Apply upward velocity: this effectively means 'velocity += jump power' // Calculate initial velocity required to reach 'jumpHeight' against 'gravity' playerVelocity.y = Mathf.Sqrt(jumpHeight * -2f * gravity); } }
To set up input actions:
- Click on your
Player Input
object in the Hierarchy. - In the Inspector, locate the
Events
section and then theGameplay
section (or your custom Action Map). - Ensure your Jump action is configured, and its
performed
event can be subscribed to programmatically as shown above.
You can learn more about the new Input System in the Unity Input System Documentation.
- Click on your
Implementing a Jump with Rigidbody
For characters that require full physics interactions (e.g., being pushed by explosions, realistic collisions), a Rigidbody
component is used.
-
Setup:
- Add a
Rigidbody
component to your character (uncheck Is Kinematic). - Add a Collider component (e.g.,
CapsuleCollider
). - Create and attach a C# script (e.g.,
PlayerRigidbodyMovement
).
- Add a
-
Declare Variables:
using UnityEngine; public class PlayerRigidbodyMovement : MonoBehaviour { private Rigidbody rb; public float jumpForce = 8f; // The force applied for a jump private bool isGrounded; public Transform groundCheck; // An empty GameObject at the feet for ground checking public LayerMask groundLayer; public float groundCheckRadius = 0.2f;
-
Initialization and Grounded Check: For Rigidbody, gravity is often handled automatically. A custom ground check is typically needed. Physics updates should occur in
FixedUpdate
.void Awake() { rb = GetComponent<Rigidbody>(); } void FixedUpdate() // Use FixedUpdate for physics operations { // Custom ground check using a sphere overlap isGrounded = Physics.CheckSphere(groundCheck.position, groundCheckRadius, groundLayer); }
For ground checking, refer to Unity Physics.CheckSphere Documentation.
-
Jump Input and Application:
void Update() // Input detection usually in Update { if (Input.GetButtonDown("Jump") && isGrounded) { rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse); } }
ForceMode.Impulse
applies an instant force, suitable for jumps.
For more details on physics-based movement, consult the Unity Rigidbody Documentation.
Comparing CharacterController and Rigidbody for Jumping
Feature | CharacterController | Rigidbody |
---|---|---|
Physics | Manages collisions but does not directly use physics forces for movement. | Fully physics-driven, responds to gravity, forces, torque. |
Movement Control | Achieved via controller.Move() , you manage velocity. |
Controlled via rb.velocity or rb.AddForce() . |
Gravity | Must be manually applied in your script. | Handled automatically by Unity's physics engine. |
Jumping Method | Direct manipulation of playerVelocity.y . |
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse); |
Grounded Check | Built-in controller.isGrounded property, or custom. |
Requires a custom implementation (e.g., Physics.CheckSphere ). |
Best For | Player characters needing precise, non-physics-based movement. | Physics-based characters or objects requiring realistic interactions. |
Key Considerations and Best Practices
To enhance your character's jump behavior:
- Reliable Ground Check: Ensure your grounded check is accurate and prevents "mid-air jumps" while allowing jumps when barely touching the ground.
- Variable Jump Height: Allow the player to hold the jump button longer for a higher jump. This can be done by applying a continuous upward force for a short duration while the button is pressed, or by progressively reducing gravity after the initial jump impulse.
- Coyote Time: Implement a brief window after leaving a platform where the character can still jump. This makes platforming feel more forgiving.
- Jump Buffer: Store jump input for a short duration, so if the player presses jump just before landing, the jump executes immediately upon touching the ground.
- Jump Cooldown: Prevent "jump spamming" by adding a short delay between jumps.
- Animations: Integrate jump animations (start, mid-air, landing) to provide visual feedback and improve player experience.