Unity制作贪吃蛇游戏

 

  玩家通过“WASD”控制小蛇上下左右移动,蛇头撞倒食物,则食物被吃掉,蛇身体长一节,接着又出现食物,等待蛇来吃,如果蛇在移动中撞到墙或身体交叉蛇头撞倒自己身体游戏结束

  可通过游戏开始前对小蛇皮肤进行选择

  自由模式下蛇头可以穿过四周的墙

  使用本地持久化保存与读取的类——PlayerPrefs类对玩家游戏数据的存储

 

  PlayerPrefs类存储位置  传送门

  Unity圣典  传送门

  游戏项目已托管到Github上  传送门

 

 

游戏展示

 

对玩家的游戏数据记录

   游戏界面存储玩家最高分以及上一次游戏的分数

 

Unity3D_(游戏)贪吃蛇-编程之家 

 

游戏换肤

   为玩家可以选择蓝色小蛇或黄色小蛇

 

Unity3D_(游戏)贪吃蛇-编程之家 

 

游戏模式

  边界模式下蛇撞到边界判定游戏结束

  自由模式下蛇碰到边界时会从另一个边界线出来

 

Unity3D_(游戏)贪吃蛇-编程之家

 (文字最下边有游戏脚本源代码)

 

  

 

 实现过程

 

制作开始场景UI界面

 

  添加一个Canvas作为游戏开始场景并将Canvas下的Render Mode设置为Screen Space—Camera

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

    1:Screen Space-Overlay:这种模式层级视图中不需要任何的摄像机,且UI出现在所有摄像机的最前面。2:Screen Space-Camera:这种模式需要绑定一个UICamrea,它支持UI前面显示3D对象和粒子系统。3:World Space:这种模式,UI和3d对象完全一样。

Canvas 三种渲染模式如下

 

Unity3D_(游戏)贪吃蛇-编程之家

(2D游戏常用Screen Space-Camera模式,3D游戏常用Screen Space-Overlay模式)

  

  Canvas Scaler(Script)个人比较喜欢设置UI Scale Mode设置成Scale With Screen Si   根据屏幕尺寸来调整UI的缩放值 

 

  指定渲染摄像机

Unity3D_(游戏)贪吃蛇-编程之家

 

  添加游戏背景及控制面板

Unity3D_(游戏)贪吃蛇-编程之家

 

  使用UGUI制作游戏场景界面

Unity3D_(游戏)贪吃蛇-编程之家

  

  Bg(Image):制作游戏背景界面

       ControlPanel(Panel):制作游戏选项区域

  Title(Text):制作游戏标题

  Go(Image):制作游戏开始图标

      添加Button控件,制作成按钮

      添加Outline外边框和Shadow阴影组件(逼真图片按钮)

  Text:"开始"文本

 

  添加十张Image作为游戏背景图片

Unity3D_(游戏)贪吃蛇-编程之家

 

  食物作为游戏背景太鲜明时,可以把食物的透明度调为150

Unity3D_(游戏)贪吃蛇-编程之家

 

  制作Text文字背景

Unity3D_(游戏)贪吃蛇-编程之家

 

   Mode下添加一个Toggle提供玩家对模式的选择

Unity3D_(游戏)贪吃蛇-编程之家

(给文字添加Outline给玩家一种朦胧感)

  

  边界模式下,蛇撞墙后判断游戏结束

  复制边界模式Toggle,修改文字为自由模式(自由模式下蛇撞墙后不会判定结束游戏)

  边界模式和自由模式玩家只能选择一个

 

  给Mode添加Toggle Group组件

  Unity3D_(游戏)贪吃蛇-编程之家

 

  将Toggle Group组件绑定给Border和NoBorder

   Unity3D_(游戏)贪吃蛇-编程之家  Unity3D_(游戏)贪吃蛇-编程之家

 

Unity3D_(游戏)贪吃蛇-编程之家

 

  is on :当前标签是否勾选

 

  同理添加小蛇皮肤属性

Unity3D_(游戏)贪吃蛇-编程之家

 

  将选择小蛇皮肤也设置成Toggle Group

  "黄色小蛇"和"自由模式" is on 去掉勾选

 

Unity3D_(游戏)贪吃蛇-编程之家

 

 

游戏场景UI界面

 

Unity3D_(游戏)贪吃蛇-编程之家

 

  ControlPanel下的按钮、文本控件

    Msg(Text):玩家选择游戏模式

    Score(Text):玩家当前得分

    Length(Text):当前蛇自身长度

    Home(Image):返回主页面按钮

    Pause(Image):停止游戏按钮

 

 

给游戏场景添加边界

 

  Bg下创建两个GameObject,设置(锚点)GameObject范围,添加Box Collider 2D作为游戏碰撞器

Unity3D_(游戏)贪吃蛇-编程之家

 

  给小蛇添加活动范围,添加一个Box Collider 2D碰撞器

  为了将活动范围标记出来,可以给碰撞其添加一个Image红色图片作为围墙

Unity3D_(游戏)贪吃蛇-编程之家

 

  修改一下碰撞器范围

Unity3D_(游戏)贪吃蛇-编程之家

 

 

制作贪吃蛇舌头并让其移动

 

  添加Image制作舌头,设置好舌头大小

Unity3D_(游戏)贪吃蛇-编程之家

 

  创建SnakeHead.cs脚本并绑定到蛇头部

Unity3D_(游戏)贪吃蛇-编程之家

 

  控制小蛇头部移动脚本

 void Move(){headPos = gameObject.transform.localPosition;gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);}

 

  添加键盘按钮事件

    private void Update(){if (Input.GetKey(KeyCode.W)){x = 0;y = step;}if (Input.GetKey(KeyCode.S)){x = 0;y = -step;}if (Input.GetKey(KeyCode.A)){x = -step;y = 0;}if (Input.GetKey(KeyCode.D)){x = step;y = 0;}}

  

  初始时及改变方向时不断让小蛇向着一个方向移动

    private void Start(){//重复调用InvokeRepeating("Move",0,velocity);x = step;y = 0;}

 

  

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

Invoke() 方法是 Unity3D 的一种委托机制如: Invoke("Test", 5);   它的意思是:5 秒之后调用 Test() 方法;使用 Invoke() 方法需要注意 3点:1 :它应该在 脚本的生命周期里的(Start、Update、OnGUI、FixedUpdate、LateUpdate)中被调用;2:Invoke(); 不能接受含有参数的方法;3:在 Time.ScaleTime = 0; 时, Invoke() 无效,因为它不会被调用到Invoke() 也支持重复调用:InvokeRepeating("Test", 2 , 3); 这个方法的意思是指:2 秒后调用 Test() 方法,并且之后每隔 3 秒调用一次 Test() 方法还有两个重要的方法:IsInvoking:用来判断某方法是否被延时,即将执行
CancelInvoke:取消该脚本上的所有延时方法

Unity中Invoke 和 InvokeRepeating的区别

 

Unity3D_(游戏)贪吃蛇-编程之家

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SnakeHead : MonoBehaviour {public float velocity=0.35f;public int step;private int x;private int y;private Vector3 headPos;private void Start(){//重复调用InvokeRepeating("Move",0,velocity);x = step;y = 0;}private void Update(){if (Input.GetKey(KeyCode.W)){x = 0;y = step;}if (Input.GetKey(KeyCode.S)){x = 0;y = -step;}if (Input.GetKey(KeyCode.A)){x = -step;y = 0;}if (Input.GetKey(KeyCode.D)){x = step;y = 0;}}void Move(){headPos = gameObject.transform.localPosition;gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);}
}

SnakeHead.cs

 

  给小蛇头部添加转动时改变头部方向动画

 private void Update(){if (Input.GetKey(KeyCode.W)){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 0);x = 0;y = step;}if (Input.GetKey(KeyCode.S)){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);x = 0;y = -step;}if (Input.GetKey(KeyCode.A)){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);x = -step;y = 0;}if (Input.GetKey(KeyCode.D)){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);x = step;y = 0;}}

 

Unity3D_(游戏)贪吃蛇-编程之家

 

  发现小球向左走时还能向右走,向下走时还能向上走

  判断按键方法时候可以对方向进行一个判断

    private void Update(){if (Input.GetKey(KeyCode.W) &&  y!=-step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 0);x = 0;y = step;}if (Input.GetKey(KeyCode.S) &&  y!=step  ){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);x = 0;y = -step;}if (Input.GetKey(KeyCode.A) && x!=step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);x = -step;y = 0;}if (Input.GetKey(KeyCode.D) &&  x!=-step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);x = step;y = 0;}}

 

  添加按下空格加快贪吃蛇向前移动速度

        if (Input.GetKeyDown(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move",0,velocity - 0.2f);}if (Input.GetKeyUp(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move", 0, velocity);}

 

  Unity圣典  传送门

  MonoBehaviour.CancelInvoke 取消调用

     MonoBehaviour.InvokeRepeating 重复调用

Unity3D_(游戏)贪吃蛇-编程之家

 

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SnakeHead : MonoBehaviour {public float velocity=0.35f;public int step;private int x;private int y;private Vector3 headPos;private void Start(){//重复调用InvokeRepeating("Move",0,velocity);x = 0;y = step;}private void Update(){if (Input.GetKeyDown(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move",0,velocity - 0.2f);}if (Input.GetKeyUp(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move", 0, velocity);}if (Input.GetKey(KeyCode.W) &&  y!=-step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 0);x = 0;y = step;}if (Input.GetKey(KeyCode.S) &&  y!=step  ){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);x = 0;y = -step;}if (Input.GetKey(KeyCode.A) && x!=step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);x = -step;y = 0;}if (Input.GetKey(KeyCode.D) &&  x!=-step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);x = step;y = 0;}}void Move(){headPos = gameObject.transform.localPosition;gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);}
}

SnakeHead.cs

 

 

 

第一个食物的随机生成

 

  对游戏边界范围的判定

  上边界与下边界

Unity3D_(游戏)贪吃蛇-编程之家

 

  经测试

  小蛇走11步碰到上边界,走10步碰到下边界

  小蛇走19步碰到右边界,走11步碰到左边界

 

  将食物和小蛇设置为预制体

Unity3D_(游戏)贪吃蛇-编程之家

 

  创建一个GameObject空物体对象挂在脚本和预制体

Unity3D_(游戏)贪吃蛇-编程之家

 

  游戏初始时获得游戏物体,并且生成食物

 private void Start(){foodHolder = GameObject.Find("FoodHolder").transform;MakeFood();}

  

  随机生成食物的位置

 public int xlimit = 18;public int ylimit = 10;//x轴活动空间不对称问题,对x轴的偏移值public int xoffset = 11;     void MakeFood(){//生成x和y的随机值int x = Random.Range(-xlimit + xoffset,xlimit);int y = Random.Range(-ylimit,ylimit);//通过小蛇自身的步数长度来计算食物的活动空间food.transform.localPosition = new Vector3(x * 20, y * 20, 0);}

 

  随机生成食物的种类和位置

 void MakeFood(){int index = Random.Range(0,foodSprites.Length);GameObject food = Instantiate(foodPrefab);food.GetComponent<Image>().sprite = foodSprites[index];food.transform.SetParent(foodHolder,false);int x = Random.Range(-xlimit + xoffset,xlimit);int y = Random.Range(-ylimit,ylimit);//通过小蛇自身的步数长度来计算食物的活动空间food.transform.localPosition = new Vector3(x * 25, y * 25, 0);}

 

Unity3D_(游戏)贪吃蛇-编程之家

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class FoodMaker : MonoBehaviour {public int xlimit = 18;public int ylimit = 10;//x轴活动空间不对称问题,对x轴的偏移值public int xoffset = 11;public GameObject foodPrefab;public Sprite[] foodSprites;private Transform foodHolder;private void Start(){foodHolder = GameObject.Find("FoodHolder").transform;MakeFood();}void MakeFood(){int index = Random.Range(0,foodSprites.Length);GameObject food = Instantiate(foodPrefab);food.GetComponent<Image>().sprite = foodSprites[index];food.transform.SetParent(foodHolder,false);int x = Random.Range(-xlimit + xoffset,xlimit);int y = Random.Range(-ylimit,ylimit);//通过小蛇自身的步数长度来计算食物的活动空间food.transform.localPosition = new Vector3(x * 25, y * 25, 0);}
}

FoodMaker.cs

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SnakeHead : MonoBehaviour {public float velocity=0.35f;public int step;private int x;private int y;private Vector3 headPos;private void Start(){//重复调用InvokeRepeating("Move",0,velocity);x = 0;y = step;}private void Update(){if (Input.GetKeyDown(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move",0,velocity - 0.2f);}if (Input.GetKeyUp(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move", 0, velocity);}if (Input.GetKey(KeyCode.W) &&  y!=-step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 0);x = 0;y = step;}if (Input.GetKey(KeyCode.S) &&  y!=step  ){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);x = 0;y = -step;}if (Input.GetKey(KeyCode.A) && x!=step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);x = -step;y = 0;}if (Input.GetKey(KeyCode.D) &&  x!=-step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);x = step;y = 0;}}void Move(){headPos = gameObject.transform.localPosition;gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);}
}

SnakeHead.cs

 

 

吃掉食物(销毁)以及食物的随机生成

 

  给蛇头添加Box Collider 2D碰撞器,为避免蛇头未碰撞食物时碰撞器就碰撞到食物,可以设置碰撞器范围比蛇头小一圈

  勾选Is Trigger,当物体碰到食物及边界时,可以进入边界再判定游戏结束

Unity3D_(游戏)贪吃蛇-编程之家

 

  给蛇头添加Rigidbody 2D碰撞器,设置重力 Gravity Scale为0  (不然蛇头在开始游戏时就会不断往下掉)

 

  同理,给食物预设体Food添加Box Collider 2D碰撞器

Unity3D_(游戏)贪吃蛇-编程之家

 

  新创建一个Food标签作为标记

Unity3D_(游戏)贪吃蛇-编程之家

 

  将Food预设体标签设置为Food

Unity3D_(游戏)贪吃蛇-编程之家

 

  SnakeHead.cs中添加食物碰撞生成新食物方法

    private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.CompareTag("Food")){Destroy(collision.gameObject);FoodMaker.Instance.MakeFood();}}

 

  FoodMaker.cs

 

  添加一个单例模式

 

    //单例模式private static FoodMaker _instance;//可以通过外部去调用方法修改_instance的值public static FoodMaker Instance{get{return _instance;}}//初始化private void Awake(){_instance = this;}

 

 

Unity3D_(游戏)贪吃蛇-编程之家

 

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class FoodMaker : MonoBehaviour {//单例模式private static FoodMaker _instance;public static FoodMaker Instance{get{return _instance;}}public int xlimit = 17;public int ylimit = 8;//x轴活动空间不对称问题,对x轴的偏移值public int xoffset = 11;public GameObject foodPrefab;public Sprite[] foodSprites;private Transform foodHolder;private void Awake(){_instance = this;}private void Start(){foodHolder = GameObject.Find("FoodHolder").transform;MakeFood();}public void MakeFood(){int index = Random.Range(0,foodSprites.Length);GameObject food = Instantiate(foodPrefab);food.GetComponent<Image>().sprite = foodSprites[index];food.transform.SetParent(foodHolder,false);int x = Random.Range(-xlimit + xoffset,xlimit);int y = Random.Range(-ylimit,ylimit);//通过小蛇自身的步数长度来计算食物的活动空间food.transform.localPosition = new Vector3(x * 25, y * 25, 0);}
}

FoodMaker.cs

 

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SnakeHead : MonoBehaviour {public float velocity=0.35f;public int step;private int x;private int y;private Vector3 headPos;private void Start(){//重复调用InvokeRepeating("Move",0,velocity);x = 0;y = step;}private void Update(){if (Input.GetKeyDown(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move",0,velocity - 0.2f);}if (Input.GetKeyUp(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move", 0, velocity);}if (Input.GetKey(KeyCode.W) &&  y!=-step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 0);x = 0;y = step;}if (Input.GetKey(KeyCode.S) &&  y!=step  ){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);x = 0;y = -step;}if (Input.GetKey(KeyCode.A) && x!=step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);x = -step;y = 0;}if (Input.GetKey(KeyCode.D) &&  x!=-step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);x = step;y = 0;}}void Move(){headPos = gameObject.transform.localPosition;gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);}private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.CompareTag("Food")){Destroy(collision.gameObject);FoodMaker.Instance.MakeFood();}}}

SnakeHead.cs

 

 

 

蛇身吃掉食物的变长

 

  添加一个Image放置蛇身图片,添加Box Collider 2D碰撞器(碰撞器的范围不用太大,以免对食物产生不可描述的误操作)

Unity3D_(游戏)贪吃蛇-编程之家

 

  SnakeHead.cs脚本中生成蛇身

  创建一个集合,用来保存蛇身部分(两张图片不断轮流交换)

 public List<RectTransform> bodyList = new List<RectTransform>();public GameObject bodyPrefab;public Sprite[] bodySprites = new Sprite[2];

 

  生成蛇身体方法

    void Grow(){int index = (bodyList.Count % 2 == 0) ? 0 : 1;GameObject body = Instantiate(bodyPrefab);body.GetComponent<Image>().sprite = bodySprites[index];body.transform.SetParent(canvas,false);bodyList.Add(body.transform);}

 

 

 

蛇生体移动的方法

 

   创建一个链表,当蛇吃了食物后,将蛇身放置到链表中

 public List<Transform> bodyList = new List<Transform>();

 

  将图片放置到bodySprites中(两张),存放的都是bodyPrefab

    public GameObject bodyPrefab;public Sprite[] bodySprites = new Sprite[2];private void Awake(){canvas = GameObject.Find("Canvas").transform;}

 

  Unity中将预制体与贪吃蛇头部绑定一下

Unity3D_(游戏)贪吃蛇-编程之家

 

   蛇碰到食物后开始生成蛇身

    void Grow(){int index = (bodyList.Count % 2 == 0) ? 0 : 1;GameObject body = Instantiate(bodyPrefab,new Vector3(200000,2000000,0),Quaternion.identity);body.GetComponent<Image>().sprite = bodySprites[index];body.transform.SetParent(canvas, false);bodyList.Add(body.transform);}

 

    private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.CompareTag("Food")){Destroy(collision.gameObject);Grow();FoodMaker.Instance.MakeFood();}}

 

Unity3D_(游戏)贪吃蛇-编程之家

 

  

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class FoodMaker : MonoBehaviour {//单例模式private static FoodMaker _instance;public static FoodMaker Instance{get{return _instance;}}public int xlimit = 18;public int ylimit = 9;//x轴活动空间不对称问题,对x轴的偏移值public int xoffset = 10;public GameObject foodPrefab;public Sprite[] foodSprites;private Transform foodHolder;private void Awake(){_instance = this;}private void Start(){foodHolder = GameObject.Find("FoodHolder").transform;MakeFood();}public void MakeFood(){int index = Random.Range(0,foodSprites.Length);GameObject food = Instantiate(foodPrefab);food.GetComponent<Image>().sprite = foodSprites[index];food.transform.SetParent(foodHolder,false);int x = Random.Range(-xlimit + xoffset,xlimit);int y = Random.Range(-ylimit,ylimit);food.transform.localPosition = new Vector3(x * 20, y * 20, 0);//food.transform.localPosition = new Vector3( x,  y, 0);
    }
}

FoodMaker.cs

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;public class SnakeHead : MonoBehaviour {public List<Transform> bodyList = new List<Transform>();public float velocity=0.35f;public int step;private int x;private int y;private Vector3 headPos;private Transform canvas;public GameObject bodyPrefab;public Sprite[] bodySprites = new Sprite[2];private void Awake(){canvas = GameObject.Find("Canvas").transform;}private void Start(){//重复调用InvokeRepeating("Move",0,velocity);x = 0;y = step;}private void Update(){if (Input.GetKeyDown(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move",0,velocity - 0.3f);}if (Input.GetKeyUp(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move", 0, velocity);}if (Input.GetKey(KeyCode.W) &&  y!=-step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 0);x = 0;y = step;}if (Input.GetKey(KeyCode.S) &&  y!=step  ){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);x = 0;y = -step;}if (Input.GetKey(KeyCode.A) && x!=step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);x = -step;y = 0;}if (Input.GetKey(KeyCode.D) &&  x!=-step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);x = step;y = 0;}}void Move(){//保存下来蛇头移动前的位置headPos = gameObject.transform.localPosition;//蛇头向期望位置移动gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);if (bodyList.Count > 0){//由于是双色蛇身,此方法弃用//将蛇尾移动到蛇头移动前的位置// bodyList.Last().localPosition = headPos;//将蛇尾在List中的位置跟新到最前// bodyList.Insert(0, bodyList.Last());//溢出List最末尾的蛇尾引用// bodyList.RemoveAt(bodyList.Count - 1);//从后面开始移动蛇身for(int i =bodyList.Count-2;i>=0 ;i--){//每一个蛇身都移动到它前面一个bodyList[i + 1].localPosition = bodyList[i].localPosition;}//第一个蛇身移动到蛇头移动前的位置bodyList[0].localPosition = headPos;}}void Grow(){int index = (bodyList.Count % 2 == 0) ? 0 : 1;GameObject body = Instantiate(bodyPrefab,new Vector3(200000,2000000,0),Quaternion.identity);body.GetComponent<Image>().sprite = bodySprites[index];body.transform.SetParent(canvas, false);bodyList.Add(body.transform);}private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.CompareTag("Food")){Destroy(collision.gameObject);Grow();FoodMaker.Instance.MakeFood();}}}

SnakeHead.cs

 

 

游戏的自由模式

 

  当小蛇撞到上边界时再往下走一步后从下边界出现

  当小蛇撞到下边界时再往上走一步后从上边界出现

  当小蛇撞到上边界时再往下走一步后从下边界出现

  当小蛇撞到上边界时再往下走一步后从下边界出现

 

     switch(collision.gameObject.name){case "Up":transform.localPosition = new Vector3(transform.localPosition.x,-transform.localPosition.y+20,transform.localPosition.z);break;case "Down":transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y-20, transform.localPosition.z);break;case "Left":transform.localPosition = new Vector3(-transform.localPosition.x+140,transform.localPosition.y , transform.localPosition.z);break;case "Right":transform.localPosition = new Vector3(-transform.localPosition.x+170, transform.localPosition.y, transform.localPosition.z);break;}

 

Unity3D_(游戏)贪吃蛇-编程之家

 

 

奖励目标的生成

 

  添加一个Reward(Image)作为奖励目标背景图片

Unity3D_(游戏)贪吃蛇-编程之家

 

  调整奖励背景图片和食物大小保持一样,并添加Box Collider 2D组件

Unity3D_(游戏)贪吃蛇-编程之家

  

  将Resward作为预制体

  FoodMaker.cs上绑定rewardPrefabs预制体

    public GameObject rewardPrefab;

 

  Unity3D_(游戏)贪吃蛇-编程之家

 

   判断是否生成道具

  public void MakeFood(bool isReward){int index = Random.Range(0,foodSprites.Length);GameObject food = Instantiate(foodPrefab);food.GetComponent<Image>().sprite = foodSprites[index];food.transform.SetParent(foodHolder,false);int x = Random.Range(-xlimit + xoffset,xlimit);int y = Random.Range(-ylimit,ylimit);food.transform.localPosition = new Vector3(x * 20, y * 20, 0);//food.transform.localPosition = new Vector3( x,  y, 0);if(isReward==true){GameObject reward = Instantiate(rewardPrefab);reward.transform.SetParent(foodHolder, false);x = Random.Range(-xlimit + xoffset, xlimit);y = Random.Range(-ylimit, ylimit);reward.transform.localPosition = new Vector3(x * 20, y * 20, 0);}}

 

   当蛇吃到食物后,有百分之20的机率生成道具

 if (collision.gameObject.CompareTag("Food")){Destroy(collision.gameObject);Grow();if (Random.Range(0,100)<20){FoodMaker.Instance.MakeFood(true);}else{FoodMaker.Instance.MakeFood(false);}}

 

  当蛇吃到道具时,道具销毁

 else if(collision.gameObject.CompareTag("Reward")){Destroy(collision.gameObject);Grow();}

 

  Unity3D_(游戏)贪吃蛇-编程之家

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;public class SnakeHead : MonoBehaviour {public List<Transform> bodyList = new List<Transform>();public float velocity=0.35f;public int step;private int x;private int y;private Vector3 headPos;private Transform canvas;public GameObject bodyPrefab;public Sprite[] bodySprites = new Sprite[2];private void Awake(){canvas = GameObject.Find("Canvas").transform;}private void Start(){//重复调用InvokeRepeating("Move",0,velocity);x = 0;y = step;}private void Update(){if (Input.GetKeyDown(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move",0,velocity - 0.3f);}if (Input.GetKeyUp(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move", 0, velocity);}if (Input.GetKey(KeyCode.W) &&  y!=-step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 0);x = 0;y = step;}if (Input.GetKey(KeyCode.S) &&  y!=step  ){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);x = 0;y = -step;}if (Input.GetKey(KeyCode.A) && x!=step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);x = -step;y = 0;}if (Input.GetKey(KeyCode.D) &&  x!=-step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);x = step;y = 0;}}void Move(){//保存下来蛇头移动前的位置headPos = gameObject.transform.localPosition;//蛇头向期望位置移动gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);if (bodyList.Count > 0){//由于是双色蛇身,此方法弃用//将蛇尾移动到蛇头移动前的位置// bodyList.Last().localPosition = headPos;//将蛇尾在List中的位置跟新到最前// bodyList.Insert(0, bodyList.Last());//溢出List最末尾的蛇尾引用// bodyList.RemoveAt(bodyList.Count - 1);//从后面开始移动蛇身for(int i =bodyList.Count-2;i>=0 ;i--){//每一个蛇身都移动到它前面一个bodyList[i + 1].localPosition = bodyList[i].localPosition;}//第一个蛇身移动到蛇头移动前的位置bodyList[0].localPosition = headPos;}}void Grow(){int index = (bodyList.Count % 2 == 0) ? 0 : 1;GameObject body = Instantiate(bodyPrefab,new Vector3(200000,2000000,0),Quaternion.identity);body.GetComponent<Image>().sprite = bodySprites[index];body.transform.SetParent(canvas, false);bodyList.Add(body.transform);}private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.CompareTag("Food")){Destroy(collision.gameObject);Grow();if (Random.Range(0,100)<20){FoodMaker.Instance.MakeFood(true);}else{FoodMaker.Instance.MakeFood(false);}}else if(collision.gameObject.CompareTag("Reward")){Destroy(collision.gameObject);Grow();}else if(collision.gameObject.CompareTag("Body")){Debug.Log("Die");}else{switch(collision.gameObject.name){case "Up":transform.localPosition = new Vector3(transform.localPosition.x,-transform.localPosition.y+20,transform.localPosition.z);break;case "Down":transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y-20, transform.localPosition.z);break;case "Left":transform.localPosition = new Vector3(-transform.localPosition.x+140,transform.localPosition.y , transform.localPosition.z);break;case "Right":transform.localPosition = new Vector3(-transform.localPosition.x+170, transform.localPosition.y, transform.localPosition.z);break;}}}}

SnakeHead.cs

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class FoodMaker : MonoBehaviour {//单例模式private static FoodMaker _instance;public static FoodMaker Instance{get{return _instance;}}public int xlimit = 18;public int ylimit = 9;//x轴活动空间不对称问题,对x轴的偏移值public int xoffset = 10;public GameObject foodPrefab;public GameObject rewardPrefab;public Sprite[] foodSprites;private Transform foodHolder;private void Awake(){_instance = this;}private void Start(){foodHolder = GameObject.Find("FoodHolder").transform;MakeFood(false);}public void MakeFood(bool isReward){int index = Random.Range(0,foodSprites.Length);GameObject food = Instantiate(foodPrefab);food.GetComponent<Image>().sprite = foodSprites[index];food.transform.SetParent(foodHolder,false);int x = Random.Range(-xlimit + xoffset,xlimit);int y = Random.Range(-ylimit,ylimit);food.transform.localPosition = new Vector3(x * 20, y * 20, 0);//food.transform.localPosition = new Vector3( x,  y, 0);if(isReward==true){GameObject reward = Instantiate(rewardPrefab);reward.transform.SetParent(foodHolder, false);x = Random.Range(-xlimit + xoffset, xlimit);y = Random.Range(-ylimit, ylimit);reward.transform.localPosition = new Vector3(x * 20, y * 20, 0);}}
}

FoodMaker.cs

 

 

分数与长度与游戏背景切换

 

  新建一个脚本MainUIController.cs来存储蛇的分数与长度

Unity3D_(游戏)贪吃蛇-编程之家

 

  分数的单例模式

 //单例模式private static MainUIController _instance;public static MainUIController Instance{get{return _instance;}}

  

  游戏加分方法  默认吃到一个食物加5分1个长度  获得道具加分会更高

public void UpdateUI(int s = 5,int l = 1){score += s;length += l;scoreText.text ="得分:\n"+score;lengthText.text = "长度\n" + length;}

 

  当蛇吃到食物或道具时调用UpdateUI()方法

 if (collision.gameObject.CompareTag("Food")){Destroy(collision.gameObject);MainUIController.Instance.UpdateUI();Grow();if (Random.Range(0,100)<20){FoodMaker.Instance.MakeFood(true);}else{FoodMaker.Instance.MakeFood(false);}}else if(collision.gameObject.CompareTag("Reward")){Destroy(collision.gameObject);MainUIController.Instance.UpdateUI(Random.Range(5,15)*10);Grow();}

 

  当分数达到一定数值时能进行游戏背景变色

    private void Update(){switch (score / 100){case 3:ColorUtility.TryParseHtmlString("#CCEEFFFF",out tempColor);bgImage.color=tempColor;msgText.text = "阶段" + 2;break;case 5:ColorUtility.TryParseHtmlString("#CCEEFFFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段" + 3;break;case 7:ColorUtility.TryParseHtmlString("#CCFFDBFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段" + 4;break;case 9:ColorUtility.TryParseHtmlString("#EBFFCCFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段" + 5;break;case 11:ColorUtility.TryParseHtmlString("#FFDACCFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段 x";break;}}

 

  将脚本放在Script游戏物体上,并绑定分数版、背景等

Unity3D_(游戏)贪吃蛇-编程之家

 

 Unity3D_(游戏)贪吃蛇-编程之家

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;public class SnakeHead : MonoBehaviour {public List<Transform> bodyList = new List<Transform>();public float velocity=0.35f;public int step;private int x;private int y;private Vector3 headPos;private Transform canvas;public GameObject bodyPrefab;public Sprite[] bodySprites = new Sprite[2];private void Awake(){canvas = GameObject.Find("Canvas").transform;}private void Start(){//重复调用InvokeRepeating("Move",0,velocity);x = 0;y = step;}private void Update(){if (Input.GetKeyDown(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move",0,velocity - 0.3f);}if (Input.GetKeyUp(KeyCode.Space)){CancelInvoke();InvokeRepeating("Move", 0, velocity);}if (Input.GetKey(KeyCode.W) &&  y!=-step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 0);x = 0;y = step;}if (Input.GetKey(KeyCode.S) &&  y!=step  ){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);x = 0;y = -step;}if (Input.GetKey(KeyCode.A) && x!=step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);x = -step;y = 0;}if (Input.GetKey(KeyCode.D) &&  x!=-step){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);x = step;y = 0;}}void Move(){//保存下来蛇头移动前的位置headPos = gameObject.transform.localPosition;//蛇头向期望位置移动gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);if (bodyList.Count > 0){//由于是双色蛇身,此方法弃用//将蛇尾移动到蛇头移动前的位置// bodyList.Last().localPosition = headPos;//将蛇尾在List中的位置跟新到最前// bodyList.Insert(0, bodyList.Last());//溢出List最末尾的蛇尾引用// bodyList.RemoveAt(bodyList.Count - 1);//从后面开始移动蛇身for(int i =bodyList.Count-2;i>=0 ;i--){//每一个蛇身都移动到它前面一个bodyList[i + 1].localPosition = bodyList[i].localPosition;}//第一个蛇身移动到蛇头移动前的位置bodyList[0].localPosition = headPos;}}void Grow(){int index = (bodyList.Count % 2 == 0) ? 0 : 1;GameObject body = Instantiate(bodyPrefab,new Vector3(200000,2000000,0),Quaternion.identity);body.GetComponent<Image>().sprite = bodySprites[index];body.transform.SetParent(canvas, false);bodyList.Add(body.transform);}private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.CompareTag("Food")){Destroy(collision.gameObject);MainUIController.Instance.UpdateUI();Grow();if (Random.Range(0,100)<20){FoodMaker.Instance.MakeFood(true);}else{FoodMaker.Instance.MakeFood(false);}}else if(collision.gameObject.CompareTag("Reward")){Destroy(collision.gameObject);MainUIController.Instance.UpdateUI(Random.Range(5,15)*10);Grow();}else if(collision.gameObject.CompareTag("Body")){Debug.Log("Die");}else{switch(collision.gameObject.name){case "Up":transform.localPosition = new Vector3(transform.localPosition.x,-transform.localPosition.y+20,transform.localPosition.z);break;case "Down":transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y-20, transform.localPosition.z);break;case "Left":transform.localPosition = new Vector3(-transform.localPosition.x+140,transform.localPosition.y , transform.localPosition.z);break;case "Right":transform.localPosition = new Vector3(-transform.localPosition.x+170, transform.localPosition.y, transform.localPosition.z);break;}}}}

SnakeHead.cs

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class FoodMaker : MonoBehaviour {//单例模式private static FoodMaker _instance;public static FoodMaker Instance{get{return _instance;}}public int xlimit = 18;public int ylimit = 9;//x轴活动空间不对称问题,对x轴的偏移值public int xoffset = 10;public GameObject foodPrefab;public GameObject rewardPrefab;public Sprite[] foodSprites;private Transform foodHolder;private void Awake(){_instance = this;}private void Start(){foodHolder = GameObject.Find("FoodHolder").transform;MakeFood(false);}public void MakeFood(bool isReward){int index = Random.Range(0,foodSprites.Length);GameObject food = Instantiate(foodPrefab);food.GetComponent<Image>().sprite = foodSprites[index];food.transform.SetParent(foodHolder,false);int x = Random.Range(-xlimit + xoffset,xlimit);int y = Random.Range(-ylimit,ylimit);food.transform.localPosition = new Vector3(x * 20, y * 20, 0);//food.transform.localPosition = new Vector3( x,  y, 0);if(isReward==true){GameObject reward = Instantiate(rewardPrefab);reward.transform.SetParent(foodHolder, false);x = Random.Range(-xlimit + xoffset, xlimit);y = Random.Range(-ylimit, ylimit);reward.transform.localPosition = new Vector3(x * 20, y * 20, 0);}}
}

FoodMaker.cs

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class MainUIController : MonoBehaviour {//单例模式private static MainUIController _instance;public static MainUIController Instance{get{return _instance;}}public int score = 0;public int length = 0;public Text msgText;public Text scoreText;public Text lengthText;public Image bgImage;private Color tempColor;void Awake(){_instance = this;    }private void Update(){switch (score / 100){case 3:ColorUtility.TryParseHtmlString("#CCEEFFFF",out tempColor);bgImage.color=tempColor;msgText.text = "阶段" + 2;break;case 5:ColorUtility.TryParseHtmlString("#CCEEFFFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段" + 3;break;case 7:ColorUtility.TryParseHtmlString("#CCFFDBFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段" + 4;break;case 9:ColorUtility.TryParseHtmlString("#EBFFCCFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段" + 5;break;case 11:ColorUtility.TryParseHtmlString("#FFDACCFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段 x";break;}}public void UpdateUI(int s = 5,int l = 1){score += s;length += l;scoreText.text ="得分:\n"+score;lengthText.text = "长度\n" + length;}}

MainUIController.cs

 

 

暂停与返回按钮

 

  对按钮进行引用以及添加一个图片Sprite[]

    public Button pauseButton;public Sprite[] pauseSprites;

 

  设置一个变量记录游戏状态

    private bool isPause = false ;

 

  点击按钮时候对游戏状态取反

    public void Pause(){isPause = !isPause;if(isPause){Time.timeScale = 0;pauseButton.GetComponent<Image>().sprite = pauseSprites[1];}else{Time.timeScale = 1;pauseButton.GetComponent<Image>().sprite = pauseSprites[0];}}

 

  Time.timeScale  传送门

  Script中对图片、按钮进行绑定

  Unity3D_(游戏)贪吃蛇-编程之家

  

  在onclick()

 

Unity3D_(游戏)贪吃蛇-编程之家

 

Unity3D_(游戏)贪吃蛇-编程之家

 

  解决按键冲突

  按键控制器Edit->Project Settings-> Input 

    Unity3D_(游戏)贪吃蛇-编程之家

  

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

 private void Update(){if (Input.GetKeyDown(KeyCode.Space)&&MainUIController.Instance.isPause==false){CancelInvoke();InvokeRepeating("Move",0,velocity - 0.3f);}if (Input.GetKeyUp(KeyCode.Space) && MainUIController.Instance.isPause == false){CancelInvoke();InvokeRepeating("Move", 0, velocity);}if (Input.GetKey(KeyCode.W) &&  y!=-step && MainUIController.Instance.isPause == false){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 0);x = 0;y = step;}if (Input.GetKey(KeyCode.S) &&  y!=step && MainUIController.Instance.isPause == false){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);x = 0;y = -step;}if (Input.GetKey(KeyCode.A) && x!=step && MainUIController.Instance.isPause == false){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);x = -step;y = 0;}if (Input.GetKey(KeyCode.D) &&  x!=-step && MainUIController.Instance.isPause == false){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);x = step;y = 0;}}

Update()中对键盘按下事件进行处理

 

   接下来实现返回按钮

    public void Home(){UnityEngine.SceneManagement.SceneManager.LoadScene(0);}

 

  Home按钮上添加点击事件

Unity3D_(游戏)贪吃蛇-编程之家

 

Unity3D_(游戏)贪吃蛇-编程之家

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;public class SnakeHead : MonoBehaviour {public List<Transform> bodyList = new List<Transform>();public float velocity=0.35f;public int step;private int x;private int y;private Vector3 headPos;private Transform canvas;public GameObject bodyPrefab;public Sprite[] bodySprites = new Sprite[2];private void Awake(){canvas = GameObject.Find("Canvas").transform;}private void Start(){//重复调用InvokeRepeating("Move",0,velocity);x = 0;y = step;}private void Update(){if (Input.GetKeyDown(KeyCode.Space)&&MainUIController.Instance.isPause==false){CancelInvoke();InvokeRepeating("Move",0,velocity - 0.3f);}if (Input.GetKeyUp(KeyCode.Space) && MainUIController.Instance.isPause == false){CancelInvoke();InvokeRepeating("Move", 0, velocity);}if (Input.GetKey(KeyCode.W) &&  y!=-step && MainUIController.Instance.isPause == false){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 0);x = 0;y = step;}if (Input.GetKey(KeyCode.S) &&  y!=step && MainUIController.Instance.isPause == false){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);x = 0;y = -step;}if (Input.GetKey(KeyCode.A) && x!=step && MainUIController.Instance.isPause == false){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);x = -step;y = 0;}if (Input.GetKey(KeyCode.D) &&  x!=-step && MainUIController.Instance.isPause == false){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);x = step;y = 0;}}void Move(){//保存下来蛇头移动前的位置headPos = gameObject.transform.localPosition;//蛇头向期望位置移动gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);if (bodyList.Count > 0){//由于是双色蛇身,此方法弃用//将蛇尾移动到蛇头移动前的位置// bodyList.Last().localPosition = headPos;//将蛇尾在List中的位置跟新到最前// bodyList.Insert(0, bodyList.Last());//溢出List最末尾的蛇尾引用// bodyList.RemoveAt(bodyList.Count - 1);//从后面开始移动蛇身for(int i =bodyList.Count-2;i>=0 ;i--){//每一个蛇身都移动到它前面一个bodyList[i + 1].localPosition = bodyList[i].localPosition;}//第一个蛇身移动到蛇头移动前的位置bodyList[0].localPosition = headPos;}}void Grow(){int index = (bodyList.Count % 2 == 0) ? 0 : 1;GameObject body = Instantiate(bodyPrefab,new Vector3(200000,2000000,0),Quaternion.identity);body.GetComponent<Image>().sprite = bodySprites[index];body.transform.SetParent(canvas, false);bodyList.Add(body.transform);}private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.CompareTag("Food")){Destroy(collision.gameObject);MainUIController.Instance.UpdateUI();Grow();if (Random.Range(0,100)<20){FoodMaker.Instance.MakeFood(true);}else{FoodMaker.Instance.MakeFood(false);}}else if(collision.gameObject.CompareTag("Reward")){Destroy(collision.gameObject);MainUIController.Instance.UpdateUI(Random.Range(5,15)*10);Grow();}else if(collision.gameObject.CompareTag("Body")){Debug.Log("Die");}else{switch(collision.gameObject.name){case "Up":transform.localPosition = new Vector3(transform.localPosition.x,-transform.localPosition.y+20,transform.localPosition.z);break;case "Down":transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y-20, transform.localPosition.z);break;case "Left":transform.localPosition = new Vector3(-transform.localPosition.x+140,transform.localPosition.y , transform.localPosition.z);break;case "Right":transform.localPosition = new Vector3(-transform.localPosition.x+170, transform.localPosition.y, transform.localPosition.z);break;}}}}

SnakeHead.cs

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class FoodMaker : MonoBehaviour {//单例模式private static FoodMaker _instance;public static FoodMaker Instance{get{return _instance;}}public int xlimit = 18;public int ylimit = 9;//x轴活动空间不对称问题,对x轴的偏移值public int xoffset = 10;public GameObject foodPrefab;public GameObject rewardPrefab;public Sprite[] foodSprites;private Transform foodHolder;private void Awake(){_instance = this;}private void Start(){foodHolder = GameObject.Find("FoodHolder").transform;MakeFood(false);}public void MakeFood(bool isReward){int index = Random.Range(0,foodSprites.Length);GameObject food = Instantiate(foodPrefab);food.GetComponent<Image>().sprite = foodSprites[index];food.transform.SetParent(foodHolder,false);int x = Random.Range(-xlimit + xoffset,xlimit);int y = Random.Range(-ylimit,ylimit);food.transform.localPosition = new Vector3(x * 20, y * 20, 0);//food.transform.localPosition = new Vector3( x,  y, 0);if(isReward==true){GameObject reward = Instantiate(rewardPrefab);reward.transform.SetParent(foodHolder, false);x = Random.Range(-xlimit + xoffset, xlimit);y = Random.Range(-ylimit, ylimit);reward.transform.localPosition = new Vector3(x * 20, y * 20, 0);}}public void Home(){UnityEngine.SceneManagement.SceneManager.LoadScene(0);}
}

FoodMaker.cs

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class MainUIController : MonoBehaviour {//单例模式private static MainUIController _instance;public static MainUIController Instance{get{return _instance;}}public int score = 0;public int length = 0;public Text msgText;public Text scoreText;public Text lengthText;public Image bgImage;private Color tempColor;public Image pauseImage;public Sprite[] pauseSprites;public bool isPause = false ;void Awake(){_instance = this;    }private void Update(){switch (score / 100){case 0:case 1:case 2:break;case 3:case 4:ColorUtility.TryParseHtmlString("#CCEEFFFF",out tempColor);bgImage.color=tempColor;msgText.text = "阶段" + 2;break;case 5:case 6:ColorUtility.TryParseHtmlString("#CCEEFFFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段" + 3;break;case 7:case 8:ColorUtility.TryParseHtmlString("#CCFFDBFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段" + 4;break;case 9:case 10:ColorUtility.TryParseHtmlString("#EBFFCCFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段" + 5;break;case 11:case 12:case 13:ColorUtility.TryParseHtmlString("#FFDACCFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段 x";break;}}public void UpdateUI(int s = 5,int l = 1){score += s;length += l;scoreText.text ="得分:\n"+score;lengthText.text = "长度\n" + length;}public void Pause(){isPause = !isPause;if(isPause){Time.timeScale = 0;pauseImage.sprite = pauseSprites[1];}else{Time.timeScale = 1;pauseImage.sprite = pauseSprites[0];}}
}

MainUIController.cs

 

 

游戏贪吃蛇死亡处理

 

  添加游戏死亡标记

    private bool isDie = false;

 

  判断游戏死亡时触发的粒子特效

    void Die(){CancelInvoke();isDie = true;Instantiate(dieEffect);StartCoroutine(GameOver(1.0f));}

 

  通过Unity协成进行游戏的重新开始

    IEnumerator GameOver(float t){yield return new WaitForSeconds(t);UnityEngine.SceneManagement.SceneManager.LoadScene(1);}

 

  Unity3D_(游戏)贪吃蛇-编程之家

 

  游戏结束时候记录最高得分

    void Die(){CancelInvoke();isDie = true;Instantiate(dieEffect);//记录游戏的最后长度PlayerPrefs.SetInt("last1",MainUIController.Instance.length);PlayerPrefs.SetInt("lasts", MainUIController.Instance.score);//当游戏长度大于最高得分时if (PlayerPrefs.GetInt("bests", 0)<MainUIController.Instance.score){//将当前游戏长度和分数记录到best1和bests当中PlayerPrefs.SetInt("best1", MainUIController.Instance.length);PlayerPrefs.SetInt("bests", MainUIController.Instance.score);}StartCoroutine(GameOver(1.0f));}

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

1、存储值://本地化存储方式,一般用在保存玩家的偏好设置中,常见于玩家设置,游戏分数存取…………PlayerPrefs.SetFloat(string key,float value); //通过key 与value 存储,就像键值对一样。PlayerPrefs.SetInt(string key,Int value);PlayerPrefs.SetString(string key,string value);2、读取值:PlayerPrefs.GetFloat(string key);  //通过key得到存储的value值PlayerPrefs.GetInt(string key);PlayerPrefs.GetString(string key);

Unity 中PlayerPrefs类实现数据本地化存储

 

 

用户设置的存储

 

  添加StartUIController.cs脚本控制Gary开始场景界面

  获得Gary开始场景界面Text文本控件

    public Text lastText;public Text bestText;

 

  对文本控件的值进行读取刷新

    private void Awake(){lastText.text = "上次:长度" + PlayerPrefs.GetInt("last1",0)  + ",分数" + PlayerPrefs.GetInt("lasts",0);lastText.text = "最好:长度" + PlayerPrefs.GetInt("best1", 0) + ",分数" + PlayerPrefs.GetInt("bests", 0);}

 

  Gary场景中创建一个空物体游戏对象ScriptHolder挂在游戏脚本

Unity3D_(游戏)贪吃蛇-编程之家

  

 

  实现点击开始进入场景功能

  切换场景方法

    public void StartGame(){UnityEngine.SceneManagement.SceneManager.LoadScene(1);}

 

  Gary场景中Start添加onClick()点击事件

Unity3D_(游戏)贪吃蛇-编程之家

 

Unity3D_(游戏)贪吃蛇-编程之家

(可以看到此时已经实现上次分数以及最高分数的存储)

 

  动态绑定选择游戏皮肤、模式

  存储玩家的选择

 private void Start(){if (PlayerPrefs.GetString("sh", "sh01") == "sh01"){blue.isOn = true;PlayerPrefs.SetString("sh", "sh01");PlayerPrefs.SetString("sb01", "sb0101");PlayerPrefs.SetString("sb02", "sb0102");}else{yellow.isOn = true;PlayerPrefs.SetString("sh", "sh02");PlayerPrefs.SetString("sb01", "sb0201");PlayerPrefs.SetString("sb02", "sb0202");}if (PlayerPrefs.GetInt("border", 1) == 1){border.isOn = true;PlayerPrefs.SetInt("border",1);}else{noborder.isOn = true;PlayerPrefs.SetInt("border", 0);}}public void BlueSelected(bool isOn){if (isOn){PlayerPrefs.SetString("sh", "sh01");PlayerPrefs.SetString("sb01", "sb0101");PlayerPrefs.SetString("sb02", "sb0102");}}public void YellowSelected(bool isOn){if (isOn){PlayerPrefs.SetString("sh", "sh02");PlayerPrefs.SetString("sb01", "sb0201");PlayerPrefs.SetString("sb02", "sb0202");}}public void BorderSelected(bool isOn){if (isOn){PlayerPrefs.SetInt("border",1);}}public void NoBorderSelected(bool isOn){if (isOn){//自由模式PlayerPrefs.SetInt("border", 0);}}

 

Unity3D_(游戏)贪吃蛇-编程之家

 

 

 

完成换肤与数据读取

 

  使用泛型加载游戏换肤方法

    private void Awake(){canvas = GameObject.Find("Canvas").transform;//通过Resources.Load(string path)方法加载资源;gameObject.GetComponent<Image>().sprite = Resources.Load<Sprite>(PlayerPrefs.GetString("sh", "sh02"));bodySprites[0]  = Resources.Load<Sprite>(PlayerPrefs.GetString("sh01", "sh0201"));bodySprites[1]  = Resources.Load<Sprite>(PlayerPrefs.GetString("sh02", "sh0202"));}

 

Unity3D_(游戏)贪吃蛇-编程之家

 

  判断游戏模式

  添加一个模式表示位

    public bool hasBorder = true;

 

  游戏初始时默认无边界

 void Start(){if (PlayerPrefs.GetInt("border", 1)==0){hasBorder = false;//取消边界上的颜色foreach(Transform t in bgImage.gameObject.transform){t.gameObject.GetComponent<Image>().enabled = false;}}}

 

  SnakeHead.cs脚本中对游戏碰到边界死亡进行判定

if (MainUIController.Instance.hasBorder){Die();}else{switch (collision.gameObject.name){case "Up":transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y + 20, transform.localPosition.z);break;case "Down":transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y - 20, transform.localPosition.z);break;case "Left":transform.localPosition = new Vector3(-transform.localPosition.x + 140, transform.localPosition.y, transform.localPosition.z);break;case "Right":transform.localPosition = new Vector3(-transform.localPosition.x + 170, transform.localPosition.y, transform.localPosition.z);break;}}

 

Unity3D_(游戏)贪吃蛇-编程之家

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class StartUIController : MonoBehaviour {public Text lastText;public Text bestText;public Toggle blue;public Toggle yellow;public Toggle border;public Toggle noborder;private void Awake(){lastText.text = "上次:长度" + PlayerPrefs.GetInt("last1",0)  + ",分数" + PlayerPrefs.GetInt("lasts",0);bestText.text = "最好:长度" + PlayerPrefs.GetInt("best1", 0) + ",分数" + PlayerPrefs.GetInt("bests",0);}private void Start(){if (PlayerPrefs.GetString("sh", "sh01") == "sh01"){blue.isOn = true;PlayerPrefs.SetString("sh", "sh01");PlayerPrefs.SetString("sb01", "sb0101");PlayerPrefs.SetString("sb02", "sb0102");}else{yellow.isOn = true;PlayerPrefs.SetString("sh", "sh02");PlayerPrefs.SetString("sb01", "sb0201");PlayerPrefs.SetString("sb02", "sb0202");}if (PlayerPrefs.GetInt("border", 1) == 1){border.isOn = true;PlayerPrefs.SetInt("border",1);}else{noborder.isOn = true;PlayerPrefs.SetInt("border", 0);}}public void BlueSelected(bool isOn){if (isOn){PlayerPrefs.SetString("sh", "sh01");PlayerPrefs.SetString("sb01", "sb0101");PlayerPrefs.SetString("sb02", "sb0102");}}public void YellowSelected(bool isOn){if (isOn){PlayerPrefs.SetString("sh", "sh02");PlayerPrefs.SetString("sb01", "sb0201");PlayerPrefs.SetString("sb02", "sb0202");}}public void BorderSelected(bool isOn){if (isOn){PlayerPrefs.SetInt("border",1);}}public void NoBorderSelected(bool isOn){if (isOn){//自由模式PlayerPrefs.SetInt("border", 0);}}public void StartGame(){UnityEngine.SceneManagement.SceneManager.LoadScene(1);}
}

StartUIController.cs

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class MainUIController : MonoBehaviour {//单例模式private static MainUIController _instance;public static MainUIController Instance{get{return _instance;}}public int score = 0;public int length = 0;public Text msgText;public Text scoreText;public Text lengthText;public Image bgImage;private Color tempColor;public Image pauseImage;public Sprite[] pauseSprites;public bool isPause = false ;public bool hasBorder = true;void Awake(){_instance = this;    }void Start(){if (PlayerPrefs.GetInt("border", 1)==0){hasBorder = false;//取消边界上的颜色foreach(Transform t in bgImage.gameObject.transform){t.gameObject.GetComponent<Image>().enabled = false;}}}private void Update(){switch (score / 100){case 0:case 1:case 2:break;case 3:case 4:ColorUtility.TryParseHtmlString("#CCEEFFFF",out tempColor);bgImage.color=tempColor;msgText.text = "阶段" + 2;break;case 5:case 6:ColorUtility.TryParseHtmlString("#CCEEFFFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段" + 3;break;case 7:case 8:ColorUtility.TryParseHtmlString("#CCFFDBFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段" + 4;break;case 9:case 10:ColorUtility.TryParseHtmlString("#EBFFCCFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段" + 5;break;case 11:case 12:case 13:ColorUtility.TryParseHtmlString("#FFDACCFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段 x";break;}}public void UpdateUI(int s = 5,int l = 1){score += s;length += l;scoreText.text ="得分:\n"+score;lengthText.text = "长度\n" + length;}public void Pause(){isPause = !isPause;if(isPause){Time.timeScale = 0;pauseImage.sprite = pauseSprites[1];}else{Time.timeScale = 1;pauseImage.sprite = pauseSprites[0];}}
}

MainUIController.cs

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class FoodMaker : MonoBehaviour {//单例模式private static FoodMaker _instance;public static FoodMaker Instance{get{return _instance;}}public int xlimit = 18;public int ylimit = 9;//x轴活动空间不对称问题,对x轴的偏移值public int xoffset = 10;public GameObject foodPrefab;public GameObject rewardPrefab;public Sprite[] foodSprites;private Transform foodHolder;private void Awake(){_instance = this;}private void Start(){foodHolder = GameObject.Find("FoodHolder").transform;MakeFood(false);}public void MakeFood(bool isReward){int index = Random.Range(0,foodSprites.Length);GameObject food = Instantiate(foodPrefab);food.GetComponent<Image>().sprite = foodSprites[index];food.transform.SetParent(foodHolder,false);int x = Random.Range(-xlimit + xoffset,xlimit);int y = Random.Range(-ylimit,ylimit);food.transform.localPosition = new Vector3(x * 20, y * 20, 0);//food.transform.localPosition = new Vector3( x,  y, 0);if(isReward==true){GameObject reward = Instantiate(rewardPrefab);reward.transform.SetParent(foodHolder, false);x = Random.Range(-xlimit + xoffset, xlimit);y = Random.Range(-ylimit, ylimit);reward.transform.localPosition = new Vector3(x * 20, y * 20, 0);}}public void Home(){UnityEngine.SceneManagement.SceneManager.LoadScene(0);}
}

FoodMaker.cs

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;public class SnakeHead : MonoBehaviour {public List<Transform> bodyList = new List<Transform>();public float velocity=0.35f;public int step;private int x;private int y;private Vector3 headPos;private Transform canvas;private bool isDie = false;public GameObject dieEffect;public GameObject bodyPrefab;public Sprite[] bodySprites = new Sprite[2];private void Awake(){canvas = GameObject.Find("Canvas").transform;//通过Resources.Load(string path)方法加载资源;gameObject.GetComponent<Image>().sprite = Resources.Load<Sprite>(PlayerPrefs.GetString("sh", "sh02"));bodySprites[0]  = Resources.Load<Sprite>(PlayerPrefs.GetString("sb01", "sb0201"));bodySprites[1]  = Resources.Load<Sprite>(PlayerPrefs.GetString("sb02", "sb0202"));}private void Start(){//重复调用InvokeRepeating("Move",0,velocity);x = 0;y = step;}private void Update(){if (Input.GetKeyDown(KeyCode.Space)&&MainUIController.Instance.isPause==false&&isDie==false){CancelInvoke();InvokeRepeating("Move",0,velocity - 0.3f);}if (Input.GetKeyUp(KeyCode.Space) && MainUIController.Instance.isPause == false && isDie == false){CancelInvoke();InvokeRepeating("Move", 0, velocity);}if (Input.GetKey(KeyCode.W) &&  y!=-step && MainUIController.Instance.isPause == false && isDie == false){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 0);x = 0;y = step;}if (Input.GetKey(KeyCode.S) &&  y!=step && MainUIController.Instance.isPause == false && isDie == false){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);x = 0;y = -step;}if (Input.GetKey(KeyCode.A) && x!=step && MainUIController.Instance.isPause == false && isDie == false){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);x = -step;y = 0;}if (Input.GetKey(KeyCode.D) &&  x!=-step && MainUIController.Instance.isPause == false && isDie == false){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);x = step;y = 0;}}void Move(){//保存下来蛇头移动前的位置headPos = gameObject.transform.localPosition;//蛇头向期望位置移动gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);if (bodyList.Count > 0){//由于是双色蛇身,此方法弃用//将蛇尾移动到蛇头移动前的位置// bodyList.Last().localPosition = headPos;//将蛇尾在List中的位置跟新到最前// bodyList.Insert(0, bodyList.Last());//溢出List最末尾的蛇尾引用// bodyList.RemoveAt(bodyList.Count - 1);//从后面开始移动蛇身for(int i =bodyList.Count-2;i>=0 ;i--){//每一个蛇身都移动到它前面一个bodyList[i + 1].localPosition = bodyList[i].localPosition;}//第一个蛇身移动到蛇头移动前的位置bodyList[0].localPosition = headPos;}}void Grow(){int index = (bodyList.Count % 2 == 0) ? 0 : 1;GameObject body = Instantiate(bodyPrefab,new Vector3(200000,2000000,0),Quaternion.identity);body.GetComponent<Image>().sprite = bodySprites[index];body.transform.SetParent(canvas, false);bodyList.Add(body.transform);}void Die(){CancelInvoke();isDie = true;Instantiate(dieEffect);//记录游戏的最后长度PlayerPrefs.SetInt("last1",MainUIController.Instance.length);PlayerPrefs.SetInt("lasts", MainUIController.Instance.score);//当游戏长度大于最高得分时if (PlayerPrefs.GetInt("bests", 0)<MainUIController.Instance.score){//将当前游戏长度和分数记录到best1和bests当中PlayerPrefs.SetInt("best1", MainUIController.Instance.length);PlayerPrefs.SetInt("bests", MainUIController.Instance.score);}StartCoroutine(GameOver(1.0f));}IEnumerator GameOver(float t){yield return new WaitForSeconds(t);UnityEngine.SceneManagement.SceneManager.LoadScene(1);}private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.CompareTag("Food")){Destroy(collision.gameObject);MainUIController.Instance.UpdateUI();Grow();if (Random.Range(0,100)<20){FoodMaker.Instance.MakeFood(true);}else{FoodMaker.Instance.MakeFood(false);}}else if(collision.gameObject.CompareTag("Reward")){Destroy(collision.gameObject);MainUIController.Instance.UpdateUI(Random.Range(5,15)*10);Grow();}else if(collision.gameObject.CompareTag("Body")){Die();}else{if (MainUIController.Instance.hasBorder){Die();}else{switch (collision.gameObject.name){case "Up":transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y + 20, transform.localPosition.z);break;case "Down":transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y - 20, transform.localPosition.z);break;case "Left":transform.localPosition = new Vector3(-transform.localPosition.x + 140, transform.localPosition.y, transform.localPosition.z);break;case "Right":transform.localPosition = new Vector3(-transform.localPosition.x + 170, transform.localPosition.y, transform.localPosition.z);break;}}}}}

SnakeHead.cs

 

 

添加游戏音乐

 

  Main场景摄像机上绑定一个Audio Source音乐播放器

Unity3D_(游戏)贪吃蛇-编程之家

 

  吃到东西和游戏结束时分别播放两个不同的音乐

    public AudioClip eatClip;public AudioClip dieClip;

 

  

void Grow(){//播放贪吃蛇变长音乐
        AudioSource.PlayClipAtPoint(eatClip,Vector3.zero);int index = (bodyList.Count % 2 == 0) ? 0 : 1;GameObject body = Instantiate(bodyPrefab,new Vector3(200000,2000000,0),Quaternion.identity);body.GetComponent<Image>().sprite = bodySprites[index];body.transform.SetParent(canvas, false);bodyList.Add(body.transform);}void Die(){//播放死亡音乐
        AudioSource.PlayClipAtPoint(dieClip, Vector3.zero);CancelInvoke();isDie = true;Instantiate(dieEffect);//记录游戏的最后长度PlayerPrefs.SetInt("last1",MainUIController.Instance.length);PlayerPrefs.SetInt("lasts", MainUIController.Instance.score);//当游戏长度大于最高得分时if (PlayerPrefs.GetInt("bests", 0)<MainUIController.Instance.score){//将当前游戏长度和分数记录到best1和bests当中PlayerPrefs.SetInt("best1", MainUIController.Instance.length);PlayerPrefs.SetInt("bests", MainUIController.Instance.score);}StartCoroutine(GameOver(1.0f));}

 

  

Unity3D_(游戏)贪吃蛇-编程之家

 

 

 

游戏源代码

 

  控制蛇和食物脚本

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;public class SnakeHead : MonoBehaviour {public List<Transform> bodyList = new List<Transform>();public float velocity=0.35f;public int step;private int x;private int y;private Vector3 headPos;private Transform canvas;private bool isDie = false;public AudioClip eatClip;public AudioClip dieClip;public GameObject dieEffect;public GameObject bodyPrefab;public Sprite[] bodySprites = new Sprite[2];private void Awake(){canvas = GameObject.Find("Canvas").transform;//通过Resources.Load(string path)方法加载资源;gameObject.GetComponent<Image>().sprite = Resources.Load<Sprite>(PlayerPrefs.GetString("sh", "sh02"));bodySprites[0]  = Resources.Load<Sprite>(PlayerPrefs.GetString("sb01", "sb0201"));bodySprites[1]  = Resources.Load<Sprite>(PlayerPrefs.GetString("sb02", "sb0202"));}private void Start(){//重复调用InvokeRepeating("Move",0,velocity);x = 0;y = step;}private void Update(){if (Input.GetKeyDown(KeyCode.Space)&&MainUIController.Instance.isPause==false&&isDie==false){CancelInvoke();InvokeRepeating("Move",0,velocity - 0.3f);}if (Input.GetKeyUp(KeyCode.Space) && MainUIController.Instance.isPause == false && isDie == false){CancelInvoke();InvokeRepeating("Move", 0, velocity);}if (Input.GetKey(KeyCode.W) &&  y!=-step && MainUIController.Instance.isPause == false && isDie == false){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 0);x = 0;y = step;}if (Input.GetKey(KeyCode.S) &&  y!=step && MainUIController.Instance.isPause == false && isDie == false){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 180);x = 0;y = -step;}if (Input.GetKey(KeyCode.A) && x!=step && MainUIController.Instance.isPause == false && isDie == false){gameObject.transform.localRotation = Quaternion.Euler(0, 0, 90);x = -step;y = 0;}if (Input.GetKey(KeyCode.D) &&  x!=-step && MainUIController.Instance.isPause == false && isDie == false){gameObject.transform.localRotation = Quaternion.Euler(0, 0, -90);x = step;y = 0;}}void Move(){//保存下来蛇头移动前的位置headPos = gameObject.transform.localPosition;//蛇头向期望位置移动gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);if (bodyList.Count > 0){//由于是双色蛇身,此方法弃用//将蛇尾移动到蛇头移动前的位置// bodyList.Last().localPosition = headPos;//将蛇尾在List中的位置跟新到最前// bodyList.Insert(0, bodyList.Last());//溢出List最末尾的蛇尾引用// bodyList.RemoveAt(bodyList.Count - 1);//从后面开始移动蛇身for(int i =bodyList.Count-2;i>=0 ;i--){//每一个蛇身都移动到它前面一个bodyList[i + 1].localPosition = bodyList[i].localPosition;}//第一个蛇身移动到蛇头移动前的位置bodyList[0].localPosition = headPos;}}void Grow(){//播放贪吃蛇变长音乐
        AudioSource.PlayClipAtPoint(eatClip,Vector3.zero);int index = (bodyList.Count % 2 == 0) ? 0 : 1;GameObject body = Instantiate(bodyPrefab,new Vector3(200000,2000000,0),Quaternion.identity);body.GetComponent<Image>().sprite = bodySprites[index];body.transform.SetParent(canvas, false);bodyList.Add(body.transform);}void Die(){//播放死亡音乐
        AudioSource.PlayClipAtPoint(dieClip, Vector3.zero);CancelInvoke();isDie = true;Instantiate(dieEffect);//记录游戏的最后长度PlayerPrefs.SetInt("last1",MainUIController.Instance.length);PlayerPrefs.SetInt("lasts", MainUIController.Instance.score);//当游戏长度大于最高得分时if (PlayerPrefs.GetInt("bests", 0)<MainUIController.Instance.score){//将当前游戏长度和分数记录到best1和bests当中PlayerPrefs.SetInt("best1", MainUIController.Instance.length);PlayerPrefs.SetInt("bests", MainUIController.Instance.score);}StartCoroutine(GameOver(1.0f));}IEnumerator GameOver(float t){yield return new WaitForSeconds(t);UnityEngine.SceneManagement.SceneManager.LoadScene(1);}private void OnTriggerEnter2D(Collider2D collision){if (collision.gameObject.CompareTag("Food")){Destroy(collision.gameObject);MainUIController.Instance.UpdateUI();Grow();if (Random.Range(0,100)<20){FoodMaker.Instance.MakeFood(true);}else{FoodMaker.Instance.MakeFood(false);}}else if(collision.gameObject.CompareTag("Reward")){Destroy(collision.gameObject);MainUIController.Instance.UpdateUI(Random.Range(5,15)*10);Grow();}else if(collision.gameObject.CompareTag("Body")){Die();}else{if (MainUIController.Instance.hasBorder){Die();}else{switch (collision.gameObject.name){case "Up":transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y + 20, transform.localPosition.z);break;case "Down":transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y - 20, transform.localPosition.z);break;case "Left":transform.localPosition = new Vector3(-transform.localPosition.x + 140, transform.localPosition.y, transform.localPosition.z);break;case "Right":transform.localPosition = new Vector3(-transform.localPosition.x + 170, transform.localPosition.y, transform.localPosition.z);break;}}}}}

SnakeHead.cs

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class FoodMaker : MonoBehaviour {//单例模式private static FoodMaker _instance;public static FoodMaker Instance{get{return _instance;}}public int xlimit = 18;public int ylimit = 9;//x轴活动空间不对称问题,对x轴的偏移值public int xoffset = 10;public GameObject foodPrefab;public GameObject rewardPrefab;public Sprite[] foodSprites;private Transform foodHolder;private void Awake(){_instance = this;}private void Start(){foodHolder = GameObject.Find("FoodHolder").transform;MakeFood(false);}public void MakeFood(bool isReward){int index = Random.Range(0,foodSprites.Length);GameObject food = Instantiate(foodPrefab);food.GetComponent<Image>().sprite = foodSprites[index];food.transform.SetParent(foodHolder,false);int x = Random.Range(-xlimit + xoffset,xlimit);int y = Random.Range(-ylimit,ylimit);food.transform.localPosition = new Vector3(x * 20, y * 20, 0);//food.transform.localPosition = new Vector3( x,  y, 0);if(isReward==true){GameObject reward = Instantiate(rewardPrefab);reward.transform.SetParent(foodHolder, false);x = Random.Range(-xlimit + xoffset, xlimit);y = Random.Range(-ylimit, ylimit);reward.transform.localPosition = new Vector3(x * 20, y * 20, 0);}}public void Home(){UnityEngine.SceneManagement.SceneManager.LoadScene(0);}
}

FoodMaker.cs

 

 

  场景UI控制脚本 

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class MainUIController : MonoBehaviour {//单例模式private static MainUIController _instance;public static MainUIController Instance{get{return _instance;}}public int score = 0;public int length = 0;public Text msgText;public Text scoreText;public Text lengthText;public Image bgImage;private Color tempColor;public Image pauseImage;public Sprite[] pauseSprites;public bool isPause = false ;public bool hasBorder = true;void Awake(){_instance = this;    }void Start(){if (PlayerPrefs.GetInt("border", 1)==0){hasBorder = false;//取消边界上的颜色foreach(Transform t in bgImage.gameObject.transform){t.gameObject.GetComponent<Image>().enabled = false;}}}private void Update(){switch (score / 100){case 0:case 1:case 2:break;case 3:case 4:ColorUtility.TryParseHtmlString("#CCEEFFFF",out tempColor);bgImage.color=tempColor;msgText.text = "阶段" + 2;break;case 5:case 6:ColorUtility.TryParseHtmlString("#CCEEFFFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段" + 3;break;case 7:case 8:ColorUtility.TryParseHtmlString("#CCFFDBFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段" + 4;break;case 9:case 10:ColorUtility.TryParseHtmlString("#EBFFCCFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段" + 5;break;case 11:case 12:case 13:ColorUtility.TryParseHtmlString("#FFDACCFF", out tempColor);bgImage.color = tempColor;msgText.text = "阶段 x";break;}}public void UpdateUI(int s = 5,int l = 1){score += s;length += l;scoreText.text ="得分:\n"+score;lengthText.text = "长度\n" + length;}public void Pause(){isPause = !isPause;if(isPause){Time.timeScale = 0;pauseImage.sprite = pauseSprites[1];}else{Time.timeScale = 1;pauseImage.sprite = pauseSprites[0];}}
}

MainUIController.cs

 

Unity3D_(游戏)贪吃蛇-编程之家Unity3D_(游戏)贪吃蛇-编程之家

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class StartUIController : MonoBehaviour {public Text lastText;public Text bestText;public Toggle blue;public Toggle yellow;public Toggle border;public Toggle noborder;private void Awake(){lastText.text = "上次:长度" + PlayerPrefs.GetInt("last1",0)  + ",分数" + PlayerPrefs.GetInt("lasts",0);bestText.text = "最好:长度" + PlayerPrefs.GetInt("best1", 0) + ",分数" + PlayerPrefs.GetInt("bests",0);}private void Start(){if (PlayerPrefs.GetString("sh", "sh01") == "sh01"){blue.isOn = true;PlayerPrefs.SetString("sh", "sh01");PlayerPrefs.SetString("sb01", "sb0101");PlayerPrefs.SetString("sb02", "sb0102");}else{yellow.isOn = true;PlayerPrefs.SetString("sh", "sh02");PlayerPrefs.SetString("sb01", "sb0201");PlayerPrefs.SetString("sb02", "sb0202");}if (PlayerPrefs.GetInt("border", 1) == 1){border.isOn = true;PlayerPrefs.SetInt("border",1);}else{noborder.isOn = true;PlayerPrefs.SetInt("border", 0);}}public void BlueSelected(bool isOn){if (isOn){PlayerPrefs.SetString("sh", "sh01");PlayerPrefs.SetString("sb01", "sb0101");PlayerPrefs.SetString("sb02", "sb0102");}}public void YellowSelected(bool isOn){if (isOn){PlayerPrefs.SetString("sh", "sh02");PlayerPrefs.SetString("sb01", "sb0201");PlayerPrefs.SetString("sb02", "sb0202");}}public void BorderSelected(bool isOn){if (isOn){PlayerPrefs.SetInt("border",1);}}public void NoBorderSelected(bool isOn){if (isOn){//自由模式PlayerPrefs.SetInt("border", 0);}}public void StartGame(){UnityEngine.SceneManagement.SceneManager.LoadScene(1);}
}

StartUIController.cs

 

转载于:https://www.cnblogs.com/1138720556Gary/p/9733959.html