Grow
Lesson 8 of 14 in Coddy's Unity Game: Snake 3D course.
Eating makes the snake one segment longer. The new segment goes where the end of the tail was before the step: the tail moves up, and the new segment fills the cell the end has left, so the snake grows from the back.
That cell is gone once the tail has moved, so remember it first. Then, when the head has reached the food, instantiate a segment there and add it to the list, so it follows from the next step on. A segment that is made but not added never moves. A train adds a wagon at the back the same way:
Vector3 back = wagons[wagons.Count - 1].position;
// ... the train moves on ...
Transform wagon = Instantiate(wagonPrefab, back, Quaternion.identity);
wagons.Add(wagon);Grow before calling Eat(). Eat() moves the food, and the next lesson makes it look for a cell the snake does not cover, the new segment included.
Challenge
MediumThe scene sets Snake's segmentPrefab to a cube like the tail.
- Add
public Transform segmentPrefab;. - In
Step(), before the tail moves, keep the cell of the tail's last segment inVector3 tailEnd(the head's cell when the tail is empty). - When the head is on food, instantiate
segmentPrefabontailEndand add it totail, then callEat().
Press Play and eat a few, then press Check.
Try it yourself
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class Snake : MonoBehaviour
{
public float tick = 0.15f; // seconds between two steps
public int edge = 7; // the board's cells run from -edge to edge
public bool alive = true;
public List<Transform> tail = new List<Transform>();
private float timer;
private Vector3 direction = Vector3.right; // the way the head moved on its last step
private Vector3 nextDirection = Vector3.right; // the turn waiting for the next step
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;
}
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.