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
Schwer- Füge
public float speedUp = 0.005f;undpublic float minTick = 0.08f;zuSnakehinzu. - Wenn die Schlange frisst, verkürze
tickumspeedUp, aber nie unterminTick.
Drücke Play und friss: Die Schlange wird schneller. Drücke dann Check.
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 Richtungsänderung, die auf den nächsten Schritt wartet
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();
}
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.