Controller di caratteri 2D per Unity

2D Platformer è un tipo di gioco in cui il giocatore salta da una piattaforma all'altra, evita gli ostacoli e combatte i nemici, il tutto osservato da una prospettiva laterale 2D.

Sharp Coder Lettore video

Per creare un controller di personaggi platform 2D in Unity, segui i passaggi seguenti.

Il controller sarà basato sulla fisica e utilizzerà un componente Rigidbody2D.

Passi

  • Apri la scena con il tuo livello 2D (assicurati che gli sprite di livello abbiano dei collisori 2D collegati, in modo che il giocatore non cada)
  • Crea un nuovo GameObject e chiamalo "Player"
  • Crea un altro GameObject, chiamalo "player_sprite" e aggiungigli il componente Sprite Renderer
  • Assegna il tuo sprite a "player_sprite" e spostalo all'interno dell'oggetto "Player"

  • Crea un nuovo script, chiamalo "CharacterController2D" e incolla al suo interno il codice qui sotto:

CharacterController2D.cs

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

[RequireComponent(typeof(Rigidbody2D))]
[RequireComponent(typeof(CapsuleCollider2D))]

public class CharacterController2D : MonoBehaviour
{
    // Move player in 2D space
    public float maxSpeed = 3.4f;
    public float jumpHeight = 6.5f;
    public float gravityScale = 1.5f;
    public Camera mainCamera;

    bool facingRight = true;
    float moveDirection = 0;
    bool isGrounded = false;
    Vector3 cameraPos;
    Rigidbody2D r2d;
    CapsuleCollider2D mainCollider;
    Transform t;

    // Use this for initialization
    void Start()
    {
        t = transform;
        r2d = GetComponent<Rigidbody2D>();
        mainCollider = GetComponent<CapsuleCollider2D>();
        r2d.freezeRotation = true;
        r2d.collisionDetectionMode = CollisionDetectionMode2D.Continuous;
        r2d.gravityScale = gravityScale;
        facingRight = t.localScale.x > 0;

        if (mainCamera)
        {
            cameraPos = mainCamera.transform.position;
        }
    }

    // Update is called once per frame
    void Update()
    {
        // Movement controls
        if ((Input.GetKey(KeyCode.A) || Input.GetKey(KeyCode.D)) && (isGrounded || Mathf.Abs(r2d.velocity.x) > 0.01f))
        {
            moveDirection = Input.GetKey(KeyCode.A) ? -1 : 1;
        }
        else
        {
            if (isGrounded || r2d.velocity.magnitude < 0.01f)
            {
                moveDirection = 0;
            }
        }

        // Change facing direction
        if (moveDirection != 0)
        {
            if (moveDirection > 0 && !facingRight)
            {
                facingRight = true;
                t.localScale = new Vector3(Mathf.Abs(t.localScale.x), t.localScale.y, transform.localScale.z);
            }
            if (moveDirection < 0 && facingRight)
            {
                facingRight = false;
                t.localScale = new Vector3(-Mathf.Abs(t.localScale.x), t.localScale.y, t.localScale.z);
            }
        }

        // Jumping
        if (Input.GetKeyDown(KeyCode.W) && isGrounded)
        {
            r2d.velocity = new Vector2(r2d.velocity.x, jumpHeight);
        }

        // Camera follow
        if (mainCamera)
        {
            mainCamera.transform.position = new Vector3(t.position.x, cameraPos.y, cameraPos.z);
        }
    }

    void FixedUpdate()
    {
        Bounds colliderBounds = mainCollider.bounds;
        float colliderRadius = mainCollider.size.x * 0.4f * Mathf.Abs(transform.localScale.x);
        Vector3 groundCheckPos = colliderBounds.min + new Vector3(colliderBounds.size.x * 0.5f, colliderRadius * 0.9f, 0);
        // Check if player is grounded
        Collider2D[] colliders = Physics2D.OverlapCircleAll(groundCheckPos, colliderRadius);
        //Check if any of the overlapping colliders are not player collider, if so, set isGrounded to true
        isGrounded = false;
        if (colliders.Length > 0)
        {
            for (int i = 0; i < colliders.Length; i++)
            {
                if (colliders[i] != mainCollider)
                {
                    isGrounded = true;
                    break;
                }
            }
        }

        // Apply movement velocity
        r2d.velocity = new Vector2((moveDirection) * maxSpeed, r2d.velocity.y);

        // Simple debug
        Debug.DrawLine(groundCheckPos, groundCheckPos - new Vector3(0, colliderRadius, 0), isGrounded ? Color.green : Color.red);
        Debug.DrawLine(groundCheckPos, groundCheckPos - new Vector3(colliderRadius, 0, 0), isGrounded ? Color.green : Color.red);
    }
}
  • Collega lo script CharacterController2D all'oggetto "Player" (noterai che ha aggiunto anche altri componenti chiamati Rigidbody2D e CapsuleCollider2D)
  • Modifica le dimensioni di CapsuleCollider2D finché non corrispondono allo Sprite del giocatore
  • Assicurati che non ci siano collisori figli e che CapsuleCollider2D sia l'unico collisore collegato a questo lettore

Nello script CharacterController2D c'è un'opzione per assegnare la variabile Main Camera che può essere qualsiasi telecamera che seguirà il giocatore:

Il controller dei personaggi 2D è ora pronto!

Articoli suggeriti
Tutorial per il salto a muro del giocatore 3D e 2D per Unity
Aggiunta del supporto per il doppio salto a un controller di personaggi platform 2D in Unity
Controller aereo per Unity
Tutorial sul controller worm 3D per Unity
Controller planetario basato su corpo rigido per l'unità
Tutorial sul controller del lettore top-down per Unity
Controller per lettori RTS e MOBA per Unity