Mastering-2D-Platformer-Mechanics-in-Unity

Mastering 2D Platformer Mechanics in Unity

Creating smooth and responsive player controls is crucial for any 2D platformer game. In this tutorial, we’ll dive deep into the mechanics that make platformers feel great to play, and implement them step-by-step in Unity.

First, let’s create a basic player controller script:

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public float moveSpeed = 5f;
    public float jumpForce = 10f;
    public bool isGrounded = false;
    
    private Rigidbody2D rb;
    
    void Start()
    {
        rb = GetComponent();
    }
    
    void Update()
    {
        // Handle horizontal movement
        float moveHorizontal = Input.GetAxis("Horizontal");
        rb.velocity = new Vector2(moveHorizontal * moveSpeed, rb.velocity.y);
        
        // Handle jumping
        if (Input.GetButtonDown("Jump") && isGrounded)
        {
            rb.velocity = new Vector2(rb.velocity.x, jumpForce);
            isGrounded = false;
        }
    }
    
    void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.CompareTag("Ground"))
        {
            isGrounded = true;
        }
    }
}

This script provides basic movement and jumping functionality. Attach it to your player GameObject and make sure you have a Rigidbody2D component as well.

2. Implementing Coyote Time

Coyote time is a technique that allows the player to jump for a short time after leaving a platform, making the controls feel more forgiving. Let’s add it to our controller:

public class PlayerController : MonoBehaviour
{
    // ... previous code ...
    
    public float coyoteTime = 0.2f;
    private float coyoteTimeCounter;
    
    void Update()
    {
        // ... previous movement code ...
        
        if (isGrounded)
        {
            coyoteTimeCounter = coyoteTime;
        }
        else
        {
            coyoteTimeCounter -= Time.deltaTime;
        }
        
        if (Input.GetButtonDown("Jump") && coyoteTimeCounter > 0f)
        {
            rb.velocity = new Vector2(rb.velocity.x, jumpForce);
            coyoteTimeCounter = 0f;
        }
    }
    
    // ... rest of the code ...
}

3. Adding Variable Jump Height

To make jumping feel more responsive, we can implement variable jump height based on how long the jump button is held:

public class PlayerController : MonoBehaviour
{
    // ... previous code ...
    
    public float jumpTime = 0.35f;
    private float jumpTimeCounter;
    private bool isJumping;
    
    void Update()
    {
        // ... previous code ...
        
        if (Input.GetButtonDown("Jump") && coyoteTimeCounter > 0f)
        {
            rb.velocity = new Vector2(rb.velocity.x, jumpForce);
            isJumping = true;
            jumpTimeCounter = jumpTime;
            coyoteTimeCounter = 0f;
        }
        
        if (Input.GetButton("Jump") && isJumping)
        {
            if (jumpTimeCounter > 0)
            {
                rb.velocity = new Vector2(rb.velocity.x, jumpForce);
                jumpTimeCounter -= Time.deltaTime;
            }
            else
            {
                isJumping = false;
            }
        }
        
        if (Input.GetButtonUp("Jump"))
        {
            isJumping = false;
            coyoteTimeCounter = 0f;
        }
    }
    
    // ... rest of the code ...
}

4. Improving Air Control

To give the player better control while in the air, we can adjust the horizontal movement:

public class PlayerController : MonoBehaviour
{
    // ... previous code ...
    
    public float airControlMultiplier = 0.8f;
    
    void Update()
    {
        float moveHorizontal = Input.GetAxis("Horizontal");
        
        if (isGrounded)
        {
            rb.velocity = new Vector2(moveHorizontal * moveSpeed, rb.velocity.y);
        }
        else
        {
            rb.velocity = new Vector2(rb.velocity.x + (moveHorizontal * moveSpeed * airControlMultiplier * Time.deltaTime), rb.velocity.y);
            rb.velocity = new Vector2(Mathf.Clamp(rb.velocity.x, -moveSpeed, moveSpeed), rb.velocity.y);
        }
        
        // ... rest of the update code ...
    }
    
    // ... rest of the code ...
}

Conclusion

By implementing these mechanics, you’ve taken a big step towards creating a responsive and enjoyable 2D platformer in Unity. Remember to fine-tune these values to fit your specific game feel. Happy developing!

Leave a Reply

Shopping cart

0
image/svg+xml

No products in the cart.

Continue Shopping