Immer schneller
Lektion 13 von 14 im Kurs Unity-Spiel: 3D-Snake von Coddy.
Snake wird mit zunehmendem Wachstum schwieriger: Jedes Futter verkürzt den Tick ein wenig, sodass sich die Schlange schneller bewegt. Eine Untergrenze hält das Spiel spielbar: der kürzeste Tick, den es erreichen darf.
Mathf.Max gibt die größere von zwei Zahlen zurück und bildet damit eine Untergrenze: Mathf.Max(value, floor) ist niemals kleiner als floor. Ein Geschützturm, der mit jedem Upgrade schneller feuert, aber nie häufiger als alle 0.2 Sekunden:
cooldown = Mathf.Max(cooldown - 0.05f, 0.2f);Mathf.Min ist das Gegenteil, eine Obergrenze. Sie zu verwechseln, ist ein leichtes Versehen: Mit Min würde die Abklingzeit oben beim ersten Upgrade auf 0.2 sinken. Der Timer in Update() liest tick in jedem Frame aus, sodass ein kürzerer Tick ab dem nächsten Schritt zählt.
Aufgabe
SchwerDie Schlange wird schneller, wenn sie frisst.
- Füge in
Snakepublic float speedUp = 0.005f;undpublic float minTick = 0.08f;hinzu. - Wenn sie Futter frisst, verkürze tick um speedUp, aber nie unter minTick:
tick = Mathf.Max(tick - speedUp, minTick);
Drücke auf „Spielen“ und friss: Die Schlange bewegt sich jedes Mal ein wenig schneller. Drücke dann auf „Prüfen“.
Probier es selbst
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class Snake : MonoBehaviour
{
public float tick = 0.15f; // Sekunden zwischen zwei Schritten
public int edge = 7; // die Zellen des Spielfelds reichen von -edge bis edge
public bool alive = true;
public List<Transform> tail = new List<Transform>();
public Transform segmentPrefab;
private float timer;
private Vector3 direction = Vector3.right; // die Richtung, in die sich der Kopf beim letzten Schritt bewegt hat
private Vector3 nextDirection = Vector3.right; // die für den nächsten Schritt vorgemerkte Richtungsänderung
void Update()
{
if (!alive) return;
Keyboard keyboard = Keyboard.current;
if (keyboard != null)
{
if (keyboard.upArrowKey.wasPressedThisFrame || keyboard.wKey.wasPressedThisFrame) Turn(Vector3.forward);
if (keyboard.downArrowKey.wasPressedThisFrame || keyboard.sKey.wasPressedThisFrame) Turn(Vector3.back);
if (keyboard.leftArrowKey.wasPressedThisFrame || keyboard.aKey.wasPressedThisFrame) Turn(Vector3.left);
if (keyboard.rightArrowKey.wasPressedThisFrame || keyboard.dKey.wasPressedThisFrame) Turn(Vector3.right);
}
timer += Time.deltaTime;
if (timer >= tick)
{
timer -= tick;
Step();
}
}
void Turn(Vector3 newDirection)
{
if (newDirection != -direction)
{
nextDirection = newDirection;
}
}
void Step()
{
direction = nextDirection;
Vector3 next = transform.position + direction;
if (Mathf.Abs(next.x) > edge || Mathf.Abs(next.z) > edge)
{
Die();
return;
}
for (int i = 0; i < tail.Count - 1; i++)
{
if (tail[i].position == next)
{
Die();
return;
}
}
Vector3 tailEnd = tail.Count > 0 ? tail[tail.Count - 1].position : transform.position;
for (int i = tail.Count - 1; i > 0; i--)
{
tail[i].position = tail[i - 1].position;
}
if (tail.Count > 0)
{
tail[0].position = transform.position;
}
transform.position = next;
if (GameManager.Instance.IsFood(next))
{
tail.Add(Instantiate(segmentPrefab, tailEnd, Quaternion.identity));
GameManager.Instance.Eat();
}
}
public bool Occupies(Vector3 cell)
{
if (transform.position == cell) return true;
foreach (Transform segment in tail)
{
if (segment.position == cell) return true;
}
return false;
}
void Die()
{
alive = false;
GameManager.Instance.GameOver();
}
}
Alle Lektionen in Unity-Spiel: 3D-Snake
Übe selbstständig: Unity-Playground