Menu
CoddyTech

Hindernisse

Lektion 9 von 20 im Kurs Unity-Spiel: Himmelsbahnen von Coddy.

Jetzt braucht die Straße etwas zum Ausweichen. Jedes Teil bekommt ein Hindernis in der Mitte, auf einer zufällig gewählten Spur. Eine Methode namens Fill erledigt das. Sie wird für jedes neue Teil in Start aufgerufen und erneut jedes Mal, wenn ein Teil wieder nach vorne kommt.

Die ersten beiden Teile bleiben leer, damit der Spieler einen Moment Zeit hat: Road zählt die Teile, die es mit made gefüllt hat.

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) ergibt -1, 0 oder 1: Bei ganzen Zahlen wird die zweite Zahl nie ausgewählt.

Ein wiederverwendetes Teil trägt sein altes Hindernis weiterhin mit sich. Clear zerstört jedes untergeordnete Objekt, das ein Tag hat. Der Boden, die Striche und die Ränder haben das Tag Untagged, also bleiben sie:

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

Aufgabe

Einfach
  1. Füge in Road public GameObject barrierPrefab;, public int safeChunks = 2; und private int made; hinzu.
  2. Schreibe Place(chunk, prefab, lane, y, z): Die Methode erstellt das Prefab an der Position chunk.position + new Vector3(lane * laneWidth, y, z) mit der Rotation prefab.transform.rotation als untergeordnetes Objekt des Streckenabschnitts.
  3. Schreibe Fill und Clear wie oben.
  4. Rufe für jeden Abschnitt in Start Fill(chunk) auf und rufe Clear(chunk); Fill(chunk); auf, wenn ein Abschnitt nach vorne gelangt.

Probier es selbst

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;
    }
}

Alle Lektionen in Unity-Spiel: Himmelsbahnen

Übe selbstständig: Unity-Playground