Menu
CoddyTech

Obstáculos

Lección 9 de 20 del curso Juego de Unity: Carriles celestes de Coddy.

Ahora la carretera necesita algo que esquivar. Cada pieza recibe un obstáculo en el medio, en un carril aleatorio. Un método se encarga de ello: Fill, que se llama para cada pieza nueva en Start y, de nuevo, cada vez que una pieza vuelve al frente.

Las dos primeras piezas se quedan vacías para darle un momento al jugador: Road cuenta las piezas que ha rellenado en made.

void Fill(Transform chunk)
{
    made++;
    if (made <= safeChunks) return;

    int lane = Random.Range(-1, 2);
    Place(chunk, barrierPrefab, lane, 0.5f, 0f);
}

Random.Range(-1, 2) devuelve -1, 0 o 1: con números enteros, nunca se elige el segundo número.

Una pieza reciclada aún conserva su antiguo obstáculo. Clear destruye todos los elementos secundarios que tengan una etiqueta. El suelo, las líneas discontinuas y los bordes no tienen etiqueta, así que se quedan:

void Clear(Transform chunk)
{
    foreach (Transform child in chunk)
    {
        if (!child.CompareTag("Untagged")) Destroy(child.gameObject);
    }
}
challenge icon

Desafío

Fácil
  1. En Road, añade public GameObject barrierPrefab;, public int safeChunks = 2; y private int made;.
  2. Escribe Place(chunk, prefab, lane, y, z): crea el prefab en chunk.position + new Vector3(lane * laneWidth, y, z) con prefab.transform.rotation, como hijo de la pieza.
  3. Escribe Fill y Clear como arriba.
  4. Llama a Fill(chunk) para cada pieza en Start, y a Clear(chunk); Fill(chunk); cuando una pieza pase al frente.

Pruébalo tú mismo

using UnityEngine;

public class Runner : MonoBehaviour
{
    public float laneWidth = 2.5f;
    public float laneSpeed = 16f;
    public float jumpHeight = 1.6f;
    public float gravity = -40f;
    public float slideTime = 0.7f;

    public int lane;

    private CharacterController controller;
    private float fallSpeed;
    private float slide;

    void Start()
    {
        controller = GetComponent<CharacterController>();
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.LeftArrow)) lane = Mathf.Max(-1, lane - 1);
        if (Input.GetKeyDown(KeyCode.D) || Input.GetKeyDown(KeyCode.RightArrow)) lane = Mathf.Min(1, lane + 1);
        bool jump = Input.GetKeyDown(KeyCode.W) || Input.GetKeyDown(KeyCode.UpArrow) || Input.GetKeyDown(KeyCode.Space);
        if (jump && controller.isGrounded)
        {
            fallSpeed = Mathf.Sqrt(jumpHeight * -2f * gravity);
            StopSlide();
        }
        if ((Input.GetKeyDown(KeyCode.S) || Input.GetKeyDown(KeyCode.DownArrow)) && controller.isGrounded)
        {
            slide = slideTime;
            Resize(0.5f);
        }

        if (slide > 0f)
        {
            slide -= Time.deltaTime;
            if (slide <= 0f) StopSlide();
        }

        if (controller.isGrounded && fallSpeed < 0f) fallSpeed = -2f;
        fallSpeed += gravity * Time.deltaTime;

        float targetX = lane * laneWidth;
        float x = Mathf.MoveTowards(transform.position.x, targetX, laneSpeed * Time.deltaTime);
        Vector3 move = new Vector3(x - transform.position.x, fallSpeed * Time.deltaTime, 0f);
        controller.Move(move);
    }

    void StopSlide()
    {
        if (transform.localScale.y < 1f) Resize(1f);
        slide = 0f;
    }

    void Resize(float height)
    {
        controller.enabled = false;
        transform.position += Vector3.up * (height - transform.localScale.y);
        transform.localScale = new Vector3(1f, height, 1f);
        controller.enabled = true;
    }
}

Todas las lecciones de Juego de Unity: Carriles celestes

Practica por tu cuenta: Playground de Unity