Menu
CoddyTech

Bite Yourself

Lesson 10 of 14 in Coddy's Unity Game: Snake 3D course.

The snake dies when its head runs into its own tail, as it does on a wall. The test goes in the same place: on next, the cell ahead, before the head moves, so the head stays where it is when the game ends.

One segment is safe. On this step the last segment moves up too, out of its cell, so a head that follows the end of its tail into that cell never touches it. A snake of four cubes can circle a 2 by 2 square forever this way. The test leaves the last segment out by stopping one short of the end:

// every item but the last
for (int i = 0; i < items.Count - 1; i++)
{
    Debug.Log(items[i].name);
}

With the walls and the tail both deadly, the game can be lost, and the next chapter adds the score and a way to play again.

challenge icon

Challenge

Medium

In Step(), after the wall test: if next is the cell of any tail segment except the last one, call Die() and return, so the head does not move.

Press Play, grow the snake and bite your tail, 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>();
    public Transform segmentPrefab;
    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;
        }

        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;
    }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Unity Game: Snake 3D