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
MediumEach food adds a segment to the tail.
- In
Snake, addpublic Transform segmentPrefab;(the scene links it). - In
Step(), before the tail moves, keepVector3 tailEnd: the last segment's cell, or the head's cell when the tail is empty. - On food, add
Instantiate(segmentPrefab, tailEnd, Quaternion.identity)totail, then callEat().
Press Play and eat a few: the snake grows one cube each time. Then 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;
}
}
All lessons in Unity Game: Snake 3D
Practice on your own: Unity playground