Crecer
Lección 8 de 14 del curso Juego de Unity: Snake 3D de Coddy.
Al comer, la serpiente crece un segmento. El nuevo segmento aparece donde estaba el extremo de la cola antes del movimiento: la cola avanza y el nuevo segmento ocupa la celda que ha dejado libre el extremo, así que la serpiente crece por detrás.
Esa celda desaparece cuando la cola se ha movido, así que recuérdala primero. Después, cuando la cabeza haya llegado a la comida, instancia un segmento allí y añádelo a la lista para que empiece a seguirla en el siguiente movimiento. Un segmento que se crea pero no se añade nunca se mueve. Un tren añade un vagón por detrás de la misma manera:
Vector3 back = wagons[wagons.Count - 1].position;
// ... el tren sigue avanzando ...
Transform wagon = Instantiate(wagonPrefab, back, Quaternion.identity);
wagons.Add(wagon);Haz crecer la serpiente antes de llamar a Eat(). Eat() mueve la comida y, en la siguiente lección, haremos que busque una celda que la serpiente no ocupe, incluido el nuevo segmento.
Desafío
IntermedioLa escena establece segmentPrefab de Snake como un cubo, igual que la cola.
- Añade
public Transform segmentPrefab;. - En
Step(), antes de que se mueva la cola, guarda la celda del último segmento de la cola enVector3 tailEnd(la celda de la cabeza cuando la cola está vacía). - Cuando la cabeza esté sobre la comida, instancia
segmentPrefabentailEndy añádelo atail; después llama aEat().
Pulsa Play y come unos cuantos, después pulsa Check.
Pruébalo tú mismo
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class Snake : MonoBehaviour
{
public float tick = 0.15f; // segundos entre dos pasos
public int edge = 7; // las celdas del tablero van de -edge a edge
public bool alive = true;
public List<Transform> tail = new List<Transform>();
private float timer;
private Vector3 direction = Vector3.right; // la dirección en que se movió la cabeza en su último paso
private Vector3 nextDirection = Vector3.right; // el giro pendiente para el siguiente paso
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 = 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))
{
GameManager.Instance.Eat();
}
}
void Die()
{
alive = false;
}
}
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.