Saltar a contenido

Módulo 1 — La nave del jugador (25 min)

¿Qué vamos a lograr?

Una nave en pantalla que se mueve con WASD o las flechas, sin poder salirse de la vista de la cámara.

1.1 Crear el GameObject de la nave

  1. En la ventana Hierarchy, clic derecho > 2D Object > Sprites > Square (esto crea un GameObject con un Sprite Renderer ya listo). Renómbralo a Player.
  2. En el Inspector, en el componente Sprite Renderer, cambia el campo Sprite por tu nave (por ejemplo playerShip1_blue). Como el juego es vertical y los sprites de Kenney ya apuntan hacia arriba de fábrica, no hace falta rotar nada.
  3. Ubícala cerca del borde inferior de la pantalla (por ejemplo, posición X = 0, Y = -3).

Sprite Renderer de la nave configurado

1.2 El script de movimiento

Este script ya está escrito y comentado línea por línea en PlayerController.cs — solo hay que copiarlo dentro de tu propio proyecto. (Este mismo script se va a ir completando en el Módulo 2 con el disparo, así que ya lo dejamos con esa sección lista.)

using UnityEngine;

// Este script controla la nave del jugador: cómo se mueve por la pantalla y cómo dispara.
// Hay que arrastrarlo (o agregarlo con Add Component) sobre el GameObject "Player".
public class PlayerController : MonoBehaviour
{
    [Header("Movimiento")]
    // Qué tan rápido se mueve la nave (unidades por segundo).
    // Al ser "public", este valor aparece en el Inspector y se puede ajustar sin tocar código.
    public float moveSpeed = 8f;

    // Un pequeño margen para que la nave no quede "cortada" justo en el borde de la pantalla.
    public float edgePadding = 0.4f;

    [Header("Disparo")]
    // El prefab de la bala que vamos a crear cada vez que se dispara.
    // Se asigna arrastrándolo desde Assets/Prefabs hasta este campo en el Inspector.
    public GameObject bulletPrefab;

    // El punto exacto de la nave desde donde "nace" cada bala (la punta de la nave).
    public Transform firePoint;

    // Cuántos segundos mínimo deben pasar entre un disparo y el siguiente.
    public float fireRate = 0.3f;

    // Estas variables guardan los límites de la pantalla (izquierda, derecha, abajo, arriba)
    // en coordenadas del mundo del juego. Son "private" porque solo las usa este script.
    private float minX, maxX, minY, maxY;

    // Guarda el momento (según Time.time) en el que se vuelve a poder disparar.
    private float proximoDisparoDisponible;

    // Start() se ejecuta una sola vez, apenas empieza el juego.
    // Acá aprovechamos para calcular los límites de la pantalla una única vez.
    void Start()
    {
        CalcularLimitesDePantalla();
    }

    // Calcula en qué coordenadas del mundo empiezan y terminan los bordes de la cámara.
    // Así, más abajo, podemos evitar que la nave se salga de la vista del jugador.
    void CalcularLimitesDePantalla()
    {
        Camera camara = Camera.main;

        // ViewportToWorldPoint convierte una posición "de pantalla" (0,0 = esquina inferior
        // izquierda; 1,1 = esquina superior derecha) a una posición real del mundo del juego.
        Vector3 esquinaInferior = camara.ViewportToWorldPoint(new Vector3(0f, 0f, 0f));
        Vector3 esquinaSuperior = camara.ViewportToWorldPoint(new Vector3(1f, 1f, 0f));

        // Guardamos los bordes, dejando un pequeño margen (edgePadding) hacia adentro.
        minX = esquinaInferior.x + edgePadding;
        maxX = esquinaSuperior.x - edgePadding;
        minY = esquinaInferior.y + edgePadding;
        maxY = esquinaSuperior.y - edgePadding;
    }

    // Update() se ejecuta una vez por cada frame (muchas veces por segundo).
    // Separamos el trabajo en dos métodos (Mover y Disparar) para que quede ordenado.
    void Update()
    {
        Mover();
        Disparar();
    }

    void Mover()
    {
        // Input.GetAxisRaw("Horizontal") devuelve:
        //   -1 si se presiona A o la flecha izquierda
        //   +1 si se presiona D o la flecha derecha
        //    0 si no se presiona nada
        // Input.GetAxisRaw("Vertical") funciona igual, pero con W/S y las flechas arriba/abajo.
        // Estos dos ejes ya vienen configurados en Unity por defecto: no hay que tocar nada más.
        float horizontal = Input.GetAxisRaw("Horizontal");
        float vertical = Input.GetAxisRaw("Vertical");

        // Armamos un vector de dirección con esos dos valores.
        // .normalized evita que la nave vaya más rápido al moverse en diagonal
        // (sin esto, moverse en diagonal sumaría velocidad en X y en Y al mismo tiempo).
        Vector3 direccion = new Vector3(horizontal, vertical, 0f).normalized;

        // Calculamos la nueva posición: la posición actual, más la dirección,
        // multiplicada por la velocidad y por Time.deltaTime.
        // Time.deltaTime es el tiempo (en segundos) que pasó desde el último frame.
        // Multiplicar por Time.deltaTime hace que la nave se mueva a la misma velocidad
        // sin importar qué tan rápido o lento vaya el juego en cada computador.
        Vector3 nuevaPosicion = transform.position + direccion * moveSpeed * Time.deltaTime;

        // Mathf.Clamp "encierra" un valor entre un mínimo y un máximo.
        // Acá lo usamos para que la nave nunca salga de los límites de la pantalla.
        nuevaPosicion.x = Mathf.Clamp(nuevaPosicion.x, minX, maxX);
        nuevaPosicion.y = Mathf.Clamp(nuevaPosicion.y, minY, maxY);

        // Por último, aplicamos la nueva posición calculada a la nave.
        transform.position = nuevaPosicion;
    }

    void Disparar()
    {
        // Input.GetKey (a diferencia de Input.GetKeyDown) devuelve true todo el rato que la
        // tecla está apretada, por eso además controlamos un "tiempo de espera" (fireRate)
        // para que no salga una bala nueva en cada frame.
        if (Input.GetKey(KeyCode.Space) && Time.time >= proximoDisparoDisponible)
        {
            proximoDisparoDisponible = Time.time + fireRate;

            // Instantiate crea una copia nueva del prefab bulletPrefab,
            // ubicada en la posición y rotación de firePoint (la punta de la nave).
            Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
        }
    }
}

Note

Los campos bulletPrefab y firePoint van a quedar vacíos en el Inspector hasta el Módulo 2 — es normal, todavía no creamos esos objetos.

1.3 Conectar el script a la nave

  1. Selecciona el GameObject Player.
  2. Arrastra el archivo PlayerController.cs desde Assets/Scripts hasta el Inspector del Player (o usa Add Component > Player Controller).
  3. Presiona Play y prueba moverte con WASD y con las flechas.

Player Controller agregado al Inspector

Jugando en modo Play: nave moviéndose dentro de los límites

Checkpoint ✅

Al terminar este módulo se debería poder mover la nave libremente por la pantalla sin que se salga de los bordes, usando indistintamente WASD o las flechas.