Posted on

How to Make Snake

Download this Game Project

Lesson 1 Setup

In this lesson, we will go through all the steps we need to take to set up our Unity project for creating the classic game Snake. We will go over setting up our file system and as well our main game scene.

Lesson 2 Player Movement

In this lesson, we will teach you how to create the snake object and we will show you how to program the basic forward movement of the snake object.

Lesson 3 More Movement

This is the second half to creating the movement of the snake object.

Lesson 4 Changing Direction

Now that we have the basic movement of the snake object we need to program the controls to change the direction of the snake when the player presses a key on the keyboard.

Lesson 5 Growing Size

For this lesson, we will teach you how to program your snake so that it will have a size to its length. This will make it so latter when we program the eating of food the snake can get bigger and bigger.

Lesson 6 Food System

In this lesson, I will show you how to create a food generator. This mechanic makes it so that food will spawn at a random position in your scene, getting us ready for when our snake starts eating the food.

Lesson 7 Scoring

This is where we finally get to program the interaction between the snake and the food objects. This interaction will give a point to the player, make the snake grow by one, respawn the food, and add entertainment to our game.

Lesson 8 Game Over

Although our game now has an entertainment factor it is not any bit challenging which means it is still boring. To fix this we will program the game over for the game which occurs when the player runs into themselves.

Lesson 9 Main Menu

Now that the basics of our game are made we will now show you how to create the main menu for this game and how to program the transition between our menu scene and our game scene.

GameController.cs

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class GameController : MonoBehaviour {

	public int clock;
    public int maxSize;
    public int currentSize;
    public int score;
	public bool play;
	public float speed;
	public int NESW;
    public int lEdge;
    public int rEdge;
    public int tEdge;
    public int bEdge;
	public GameObject snake;
    public GameObject food;
    public Snake head;
    public Snake tail;
    public Text scoreText;
   // public UnityAds unityAds;
   public Vector2 newVect;
    public GameObject currentFood;

    private Touch initialTouch;
    private float distance;

    public bool hasTurned;

    // Use this for initialization
    void OnEnable()
    {
        Snake.hit += hit;
    }
    void Start()
    {
        InvokeRepeating("TimerInvoke", 0, .1f);
        FoodFunction();
    }
    void OnDisable()
    {
        Snake.hit -= hit;
    }

    // Update is called once per frame
    void Update()
    {
        ComChangeD();
        if(currentFood = null)
        {
            FoodFunction();
        }
    }

    void TimerInvoke()
    {
        Movement();
        StartCoroutine(checkVisible());
        if (currentSize >= maxSize)
        {
            TailFunction();
        }
        else
        {
            currentSize++;
        }
        hasTurned = false;
    }

    void Movement()
    {
        GameObject temp;
        newVect = head.transform.position;
        switch (NESW)
        {
            case 0:
                newVect = new Vector2(newVect.x, newVect.y + 1);
                break;
            case 1:
                newVect = new Vector2(newVect.x + 1, newVect.y);
                break;
            case 2:
                newVect = new Vector2(newVect.x, newVect.y - 1);
                break;
            case 3:
                newVect = new Vector2(newVect.x - 1, newVect.y);
                break;
        }
        temp = (GameObject)Instantiate(snake, newVect, transform.rotation);
        head.SetNext(temp.GetComponent<Snake>());
        head = temp.GetComponent<Snake>();

        return;
    }

    void ComChangeD()
    {
        if (!hasTurned)
        {
            if (NESW != 2 && (Input.GetKeyDown(KeyCode.UpArrow)|| Input.GetKeyDown(KeyCode.W)))
            {
                NESW = 0;
                hasTurned = true;
            }
            if (NESW != 3 && (Input.GetKeyDown(KeyCode.RightArrow) || Input.GetKeyDown(KeyCode.D)))
            {
                NESW = 1;
                hasTurned = true;
            }
            if (NESW != 0 && (Input.GetKeyDown(KeyCode.DownArrow) || Input.GetKeyDown(KeyCode.S)))
            {
                NESW = 2;
                hasTurned = true;
            }
            if (NESW != 1 && (Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetKeyDown(KeyCode.A)))
            {
                NESW = 3;
                hasTurned = true;
            }
            
        }
    }

    void TailFunction()
    {
        Snake tempSnake = tail;
        tail = tail.GetNext();
        tempSnake.removeTail();
    }

    void FoodFunction()
    {
        int xPos = Random.Range(rEdge, lEdge);
        int yPos = Random.Range(bEdge, tEdge);

        currentFood = (GameObject)Instantiate(food, new Vector2(xPos, yPos), transform.rotation);
        
    }

    IEnumerator CheckRender(GameObject IN)
    {
        yield return new WaitForEndOfFrame();
        if (IN.GetComponent<Renderer>().isVisible == false)
        {
            if (IN.tag == "Food")
            {
                Destroy(IN);
                FoodFunction();
            }
        }
    }

    void hit(string WhatWasSent)
    {
        if (WhatWasSent == "Food")
        {
            FoodFunction();
            maxSize++;
            score++;
            scoreText.text = score.ToString();
            int temp = PlayerPrefs.GetInt("HighScore");
            if (score > temp)
            {
                PlayerPrefs.SetInt("HighScore", score);
            }
        }
        if (WhatWasSent == "Snake")
        {
            CancelInvoke("TimerInvoke");
            Exit();
        }
    }

    public void Exit()
    {
        SceneManager.LoadScene(0);
    }

    void wrap()
    {
        if (NESW == 0)
        {
            head.transform.position = new Vector2(head.transform.position.x, -(head.transform.position.y - 1));
        }
        else if (NESW == 1)
        {
            head.transform.position = new Vector2(-(head.transform.position.x - 1), head.transform.position.y);
        }
        else if (NESW == 2)
        {
            head.transform.position = new Vector2(head.transform.position.x, -(head.transform.position.y + 1));
        }
        else if (NESW == 3)
        {
            head.transform.position = new Vector2(-(head.transform.position.x + 1), head.transform.position.y);
        }
    }

    IEnumerator checkVisible()
    {
        yield return new WaitForEndOfFrame();
        if (!head.GetComponent<Renderer>().isVisible)
        {
            wrap();
        }
    }
}

Snake.cs

using UnityEngine;
using System.Collections;
using System;

public class Snake : MonoBehaviour {

    public Snake next;
    static public Action<string> hit;
   // static public Action<GameObject> wrap;

    public void SetNext(Snake inner)
    {
        next = inner;
    }

    public Snake GetNext()
    {
        return next;
    }

    public void removeTail()
    {
        Destroy(this.gameObject);
    }

    void OnTriggerEnter(Collider other)
    {
        
        
        if(hit != null)
        {
            hit(other.tag);
        }
        if (other.tag == "Food")
        {
            Debug.Log(other.tag);
            Destroy(other.gameObject);
        }
    }
}

MMController.cs

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class MMController : MonoBehaviour {

    int HS;
    int LS;
    public Text HSText;
    public Text LSText;

    public GameObject mainPanel;
    public GameObject settingPanel;
    public Color onColor;
    public Color offColor;
    public Image [] speedBars;

    void Start()
    {
        if(PlayerPrefs.GetInt("Speed") == 0)
        {
            PlayerPrefs.SetInt("Speed", 10);
        }
        Speed(PlayerPrefs.GetInt("Speed"));
    }

    void Update()
    {
        if (Input.GetKey(KeyCode.Escape))
        {
            Application.Quit();
        }
    }

    void OnEnable()
    {
        HS = PlayerPrefs.GetInt("HighScore");
        LS = PlayerPrefs.GetInt("CurrentScore");
        HSText.text = HS.ToString();
        LSText.text = LS.ToString();
    }

    public void PlayFunction()
    {
        SceneManager.LoadScene(1);
    }
    public void youTubeLink()

    {
        Application.OpenURL("https://www.youtube.com/channel/UCyoayn_uVt2I55ZCUuBVRcQ");


    }

    public void SettingsFunction()
    {
        mainPanel.SetActive(false);
        settingPanel.SetActive(true);
    }

    public void BackFunction()
    {
        mainPanel.SetActive(true);
        settingPanel.SetActive(false);
    }

    public void Speed(int value)
    {
        for (int i = 0; i < value; i++)
        {
            speedBars[i].color = onColor;
        }
        for (int i = value; i < 10; i++)
        {
            speedBars[i].color = offColor;
        }
        PlayerPrefs.SetInt("Speed", value);
    }
}
using Photon.Chat;
using Photon.Pun;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class PhotonChatManager : MonoBehaviour, IChatClientListener
{
    #region Setup

    [SerializeField] GameObject joinChatButton;
    ChatClient chatClient;
    bool isConnected;
    [SerializeField] string username;

    public void UsernameOnValueChange(string valueIn)
    {
        username = valueIn;
    }

    public void ChatConnectOnClick()
    {
        isConnected = true;
        chatClient = new ChatClient(this);
        //chatClient.ChatRegion = "US";
        chatClient.Connect(PhotonNetwork.PhotonServerSettings.AppSettings.AppIdChat, PhotonNetwork.AppVersion, new AuthenticationValues(username));
        Debug.Log("Connenting");
    }

    #endregion Setup

    #region General

    [SerializeField] GameObject chatPanel;
    string privateReceiver = "";
    string currentChat;
    [SerializeField] InputField chatField;
    [SerializeField] Text chatDisplay;

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if (isConnected)
        {
            chatClient.Service();
        }

        if (chatField.text != "" &amp;&amp; Input.GetKey(KeyCode.Return))
        {
            SubmitPublicChatOnClick();
            SubmitPrivateChatOnClick();
        }
    }

    #endregion General

    #region PublicChat

    public void SubmitPublicChatOnClick()
    {
        if (privateReceiver == "")
        {
            chatClient.PublishMessage("RegionChannel", currentChat);
            chatField.text = "";
            currentChat = "";
        }
    }

    public void TypeChatOnValueChange(string valueIn)
    {
        currentChat = valueIn;
    }

    #endregion PublicChat

    #region PrivateChat

    public void ReceiverOnValueChange(string valueIn)
    {
        privateReceiver = valueIn;
    }

    public void SubmitPrivateChatOnClick()
    {
        if (privateReceiver != "")
        {
            chatClient.SendPrivateMessage(privateReceiver, currentChat);
            chatField.text = "";
            currentChat = "";
        }
    }

    #endregion PrivateChat

    #region Callbacks

    public void DebugReturn(DebugLevel level, string message)
    {
        //throw new System.NotImplementedException();
    }

    public void OnChatStateChange(ChatState state)
    {
        if(state == ChatState.Uninitialized)
        {
            isConnected = false;
            joinChatButton.SetActive(true);
            chatPanel.SetActive(false);
        }
    }

    public void OnConnected()
    {
        Debug.Log("Connected");
        joinChatButton.SetActive(false);
        chatClient.Subscribe(new string[] { "RegionChannel" });
    }

    public void OnDisconnected()
    {
        isConnected = false;
        joinChatButton.SetActive(true);
        chatPanel.SetActive(false);
    }

    public void OnGetMessages(string channelName, string[] senders, object[] messages)
    {
        string msgs = "";
        for (int i = 0; i &lt; senders.Length; i++)
        {
            msgs = string.Format("{0}: {1}", senders[i], messages[i]);

            chatDisplay.text += "\n" + msgs;

            Debug.Log(msgs);
        }

    }

    public void OnPrivateMessage(string sender, object message, string channelName)
    {
        string msgs = "";

        msgs = string.Format("(Private) {0}: {1}", sender, message);

        chatDisplay.text += "\n " + msgs;

        Debug.Log(msgs);
        
    }

    public void OnStatusUpdate(string user, int status, bool gotMessage, object message)
    {
        throw new System.NotImplementedException();
    }

    public void OnSubscribed(string[] channels, bool[] results)
    {
        chatPanel.SetActive(true);
    }

    public void OnUnsubscribed(string[] channels)
    {
        throw new System.NotImplementedException();
    }

    public void OnUserSubscribed(string channel, string user)
    {
        throw new System.NotImplementedException();
    }

    public void OnUserUnsubscribed(string channel, string user)
    {
        throw new System.NotImplementedException();
    }

    #endregion Callbacks
}