Unity制作贪吃蛇小游戏

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

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

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

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

  PlayerPrefs类存储位置  传送门

  Unity圣典  传送门

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

游戏展示

对玩家的游戏数据记录

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

游戏换肤

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

游戏模式

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

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

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

  

实现过程

制作开始场景UI界面

 

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

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

Canvas 三种渲染模式如下

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

  

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

  指定渲染摄像机

  添加游戏背景及控制面板

  使用UGUI制作游戏场景界面

  

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

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

  Title(Text):制作游戏标题

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

      添加Button控件,制作成按钮

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

  Text:"开始"文本

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

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

  制作Text文字背景

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

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

  

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

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

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

  给Mode添加Toggle Group组件

  

  将Toggle Group组件绑定给Border和NoBorder

    

  is on :当前标签是否勾选

  同理添加小蛇皮肤属性

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

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

游戏场景UI界面

  ControlPanel下的按钮、文本控件

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

    Score(Text):玩家当前得分

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

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

    Pause(Image):停止游戏按钮

给游戏场景添加边界

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

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

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

  修改一下碰撞器范围

 

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

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

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

  控制小蛇头部移动脚本

 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 = ;y = step;
}
if (Input.GetKey(KeyCode.S))
{
x = ;y = -step;
}
if (Input.GetKey(KeyCode.A))
{
x = -step;y = ;
}
if (Input.GetKey(KeyCode.D))
{
x = step;y = ;
}
}

  

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

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

  

Invoke() 方法是 Unity3D 的一种委托机制

如: Invoke("Test", );   它的意思是: 秒之后调用 Test() 方法;

使用 Invoke() 方法需要注意 3点:

 :它应该在 脚本的生命周期里的(Start、Update、OnGUI、FixedUpdate、LateUpdate)中被调用;

:Invoke(); 不能接受含有参数的方法;

:在 Time.ScaleTime = ; 时, Invoke() 无效,因为它不会被调用到

Invoke() 也支持重复调用:InvokeRepeating("Test",  , ); 

这个方法的意思是指: 秒后调用 Test() 方法,并且之后每隔  秒调用一次 Test() 方法

还有两个重要的方法:

IsInvoking:用来判断某方法是否被延时,即将执行
CancelInvoke:取消该脚本上的所有延时方法

Unity中Invoke 和 InvokeRepeating的区别

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",,velocity);
x = step;y = ;
} private void Update()
{
if (Input.GetKey(KeyCode.W))
{
x = ;y = step;
}
if (Input.GetKey(KeyCode.S))
{
x = ;y = -step;
}
if (Input.GetKey(KeyCode.A))
{
x = -step;y = ;
}
if (Input.GetKey(KeyCode.D))
{
x = step;y = ;
}
} 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(, , );
x = ;y = step;
}
if (Input.GetKey(KeyCode.S))
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = -step;
}
if (Input.GetKey(KeyCode.A))
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = -step;y = ;
}
if (Input.GetKey(KeyCode.D))
{
gameObject.transform.localRotation = Quaternion.Euler(, , -);
x = step;y = ;
}
}

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

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

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

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

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

  Unity圣典  传送门

  MonoBehaviour.CancelInvoke 取消调用

    MonoBehaviour.InvokeRepeating 重复调用

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",,velocity);
x = ;y = step;
} private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
CancelInvoke();
InvokeRepeating("Move",,velocity - 0.2f);
} if (Input.GetKeyUp(KeyCode.Space))
{
CancelInvoke();
InvokeRepeating("Move", , velocity);
} if (Input.GetKey(KeyCode.W) && y!=-step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = step;
}
if (Input.GetKey(KeyCode.S) && y!=step )
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = -step;
}
if (Input.GetKey(KeyCode.A) && x!=step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = -step;y = ;
}
if (Input.GetKey(KeyCode.D) && x!=-step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , -);
x = step;y = ;
}
} void Move()
{
headPos = gameObject.transform.localPosition;
gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);
}
}

SnakeHead.cs

第一个食物的随机生成

  对游戏边界范围的判定

  上边界与下边界

  经测试

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

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

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

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

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

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

  

  随机生成食物的位置

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

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

 void MakeFood()
{
int index = Random.Range(,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 * , y * , );
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI; public class FoodMaker : MonoBehaviour { public int xlimit = ;
public int ylimit = ;
//x轴活动空间不对称问题,对x轴的偏移值
public int xoffset = ;
public GameObject foodPrefab;
public Sprite[] foodSprites;
private Transform foodHolder; private void Start()
{
foodHolder = GameObject.Find("FoodHolder").transform;
MakeFood();
} void MakeFood()
{
int index = Random.Range(,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 * , y * , );
}
}

FoodMaker.cs

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",,velocity);
x = ;y = step;
} private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
CancelInvoke();
InvokeRepeating("Move",,velocity - 0.2f);
} if (Input.GetKeyUp(KeyCode.Space))
{
CancelInvoke();
InvokeRepeating("Move", , velocity);
} if (Input.GetKey(KeyCode.W) && y!=-step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = step;
}
if (Input.GetKey(KeyCode.S) && y!=step )
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = -step;
}
if (Input.GetKey(KeyCode.A) && x!=step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = -step;y = ;
}
if (Input.GetKey(KeyCode.D) && x!=-step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , -);
x = step;y = ;
}
} 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,当物体碰到食物及边界时,可以进入边界再判定游戏结束

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

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

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

  将Food预设体标签设置为Food

  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;
}

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 = ;
public int ylimit = ;
//x轴活动空间不对称问题,对x轴的偏移值
public int xoffset = ;
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(,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 * , y * , );
}
}

FoodMaker.cs

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",,velocity);
x = ;y = step;
} private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
CancelInvoke();
InvokeRepeating("Move",,velocity - 0.2f);
} if (Input.GetKeyUp(KeyCode.Space))
{
CancelInvoke();
InvokeRepeating("Move", , velocity);
} if (Input.GetKey(KeyCode.W) && y!=-step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = step;
}
if (Input.GetKey(KeyCode.S) && y!=step )
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = -step;
}
if (Input.GetKey(KeyCode.A) && x!=step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = -step;y = ;
}
if (Input.GetKey(KeyCode.D) && x!=-step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , -);
x = step;y = ;
}
} 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碰撞器(碰撞器的范围不用太大,以免对食物产生不可描述的误操作)

  SnakeHead.cs脚本中生成蛇身

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

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

 public GameObject bodyPrefab;
public Sprite[] bodySprites = new Sprite[];

  生成蛇身体方法

    void Grow()
{
int index = (bodyList.Count % == ) ? : ;
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[]; private void Awake()
{
canvas = GameObject.Find("Canvas").transform;
}

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

 

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

    void Grow()
{
int index = (bodyList.Count % == ) ? : ;
GameObject body = Instantiate(bodyPrefab,new Vector3(,,),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();
}
}

  

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 = ;
public int ylimit = ;
//x轴活动空间不对称问题,对x轴的偏移值
public int xoffset = ;
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(,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 * , y * , );
//food.transform.localPosition = new Vector3( x, y, 0);
}
}

FoodMaker.cs

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[]; private void Awake()
{
canvas = GameObject.Find("Canvas").transform;
} private void Start()
{
//重复调用
InvokeRepeating("Move",,velocity);
x = ;y = step;
} private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
CancelInvoke();
InvokeRepeating("Move",,velocity - 0.3f);
} if (Input.GetKeyUp(KeyCode.Space))
{
CancelInvoke();
InvokeRepeating("Move", , velocity);
} if (Input.GetKey(KeyCode.W) && y!=-step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = step;
}
if (Input.GetKey(KeyCode.S) && y!=step )
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = -step;
}
if (Input.GetKey(KeyCode.A) && x!=step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = -step;y = ;
}
if (Input.GetKey(KeyCode.D) && x!=-step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , -);
x = step;y = ;
}
} void Move()
{
//保存下来蛇头移动前的位置
headPos = gameObject.transform.localPosition;
//蛇头向期望位置移动
gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);
if (bodyList.Count > )
{
//由于是双色蛇身,此方法弃用
//将蛇尾移动到蛇头移动前的位置
// bodyList.Last().localPosition = headPos;
//将蛇尾在List中的位置跟新到最前
// bodyList.Insert(0, bodyList.Last());
//溢出List最末尾的蛇尾引用
// bodyList.RemoveAt(bodyList.Count - 1); //从后面开始移动蛇身
for(int i =bodyList.Count-;i>= ;i--)
{
//每一个蛇身都移动到它前面一个
bodyList[i + ].localPosition = bodyList[i].localPosition;
}
//第一个蛇身移动到蛇头移动前的位置
bodyList[].localPosition = headPos; }
} void Grow()
{
int index = (bodyList.Count % == ) ? : ;
GameObject body = Instantiate(bodyPrefab,new Vector3(,,),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+,transform.localPosition.z);
break;
case "Down":
transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y-, transform.localPosition.z);
break;
case "Left":
transform.localPosition = new Vector3(-transform.localPosition.x+,transform.localPosition.y , transform.localPosition.z);
break;
case "Right":
transform.localPosition = new Vector3(-transform.localPosition.x+, transform.localPosition.y, transform.localPosition.z);
break;
}

奖励目标的生成

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

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

  

  将Resward作为预制体

  FoodMaker.cs上绑定rewardPrefabs预制体

    public GameObject rewardPrefab;

  

  判断是否生成道具

  public void MakeFood(bool isReward)
{
int index = Random.Range(,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 * , y * , );
//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 * , y * , );
}
}

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

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

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

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

  

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[]; private void Awake()
{
canvas = GameObject.Find("Canvas").transform;
} private void Start()
{
//重复调用
InvokeRepeating("Move",,velocity);
x = ;y = step;
} private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
CancelInvoke();
InvokeRepeating("Move",,velocity - 0.3f);
} if (Input.GetKeyUp(KeyCode.Space))
{
CancelInvoke();
InvokeRepeating("Move", , velocity);
} if (Input.GetKey(KeyCode.W) && y!=-step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = step;
}
if (Input.GetKey(KeyCode.S) && y!=step )
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = -step;
}
if (Input.GetKey(KeyCode.A) && x!=step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = -step;y = ;
}
if (Input.GetKey(KeyCode.D) && x!=-step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , -);
x = step;y = ;
}
} void Move()
{
//保存下来蛇头移动前的位置
headPos = gameObject.transform.localPosition;
//蛇头向期望位置移动
gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);
if (bodyList.Count > )
{
//由于是双色蛇身,此方法弃用
//将蛇尾移动到蛇头移动前的位置
// bodyList.Last().localPosition = headPos;
//将蛇尾在List中的位置跟新到最前
// bodyList.Insert(0, bodyList.Last());
//溢出List最末尾的蛇尾引用
// bodyList.RemoveAt(bodyList.Count - 1); //从后面开始移动蛇身
for(int i =bodyList.Count-;i>= ;i--)
{
//每一个蛇身都移动到它前面一个
bodyList[i + ].localPosition = bodyList[i].localPosition;
}
//第一个蛇身移动到蛇头移动前的位置
bodyList[].localPosition = headPos; }
} void Grow()
{
int index = (bodyList.Count % == ) ? : ;
GameObject body = Instantiate(bodyPrefab,new Vector3(,,),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(,)<)
{
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+,transform.localPosition.z);
break;
case "Down":
transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y-, transform.localPosition.z);
break;
case "Left":
transform.localPosition = new Vector3(-transform.localPosition.x+,transform.localPosition.y , transform.localPosition.z);
break;
case "Right":
transform.localPosition = new Vector3(-transform.localPosition.x+, transform.localPosition.y, transform.localPosition.z);
break;
}
}
} }

SnakeHead.cs

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 = ;
public int ylimit = ;
//x轴活动空间不对称问题,对x轴的偏移值
public int xoffset = ;
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(,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 * , y * , );
//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 * , y * , );
}
}
}

FoodMaker.cs

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

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

  分数的单例模式

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

  

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

public void UpdateUI(int s = ,int l = )
{
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(,)<)
{
FoodMaker.Instance.MakeFood(true);
}
else
{
FoodMaker.Instance.MakeFood(false);
}
}
else if(collision.gameObject.CompareTag("Reward"))
{
Destroy(collision.gameObject);
MainUIController.Instance.UpdateUI(Random.Range(,)*);
Grow();
}

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

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

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

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[]; private void Awake()
{
canvas = GameObject.Find("Canvas").transform;
} private void Start()
{
//重复调用
InvokeRepeating("Move",,velocity);
x = ;y = step;
} private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
CancelInvoke();
InvokeRepeating("Move",,velocity - 0.3f);
} if (Input.GetKeyUp(KeyCode.Space))
{
CancelInvoke();
InvokeRepeating("Move", , velocity);
} if (Input.GetKey(KeyCode.W) && y!=-step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = step;
}
if (Input.GetKey(KeyCode.S) && y!=step )
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = -step;
}
if (Input.GetKey(KeyCode.A) && x!=step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = -step;y = ;
}
if (Input.GetKey(KeyCode.D) && x!=-step)
{
gameObject.transform.localRotation = Quaternion.Euler(, , -);
x = step;y = ;
}
} void Move()
{
//保存下来蛇头移动前的位置
headPos = gameObject.transform.localPosition;
//蛇头向期望位置移动
gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);
if (bodyList.Count > )
{
//由于是双色蛇身,此方法弃用
//将蛇尾移动到蛇头移动前的位置
// bodyList.Last().localPosition = headPos;
//将蛇尾在List中的位置跟新到最前
// bodyList.Insert(0, bodyList.Last());
//溢出List最末尾的蛇尾引用
// bodyList.RemoveAt(bodyList.Count - 1); //从后面开始移动蛇身
for(int i =bodyList.Count-;i>= ;i--)
{
//每一个蛇身都移动到它前面一个
bodyList[i + ].localPosition = bodyList[i].localPosition;
}
//第一个蛇身移动到蛇头移动前的位置
bodyList[].localPosition = headPos; }
} void Grow()
{
int index = (bodyList.Count % == ) ? : ;
GameObject body = Instantiate(bodyPrefab,new Vector3(,,),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(,)<)
{
FoodMaker.Instance.MakeFood(true);
}
else
{
FoodMaker.Instance.MakeFood(false);
}
}
else if(collision.gameObject.CompareTag("Reward"))
{
Destroy(collision.gameObject);
MainUIController.Instance.UpdateUI(Random.Range(,)*);
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+,transform.localPosition.z);
break;
case "Down":
transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y-, transform.localPosition.z);
break;
case "Left":
transform.localPosition = new Vector3(-transform.localPosition.x+,transform.localPosition.y , transform.localPosition.z);
break;
case "Right":
transform.localPosition = new Vector3(-transform.localPosition.x+, transform.localPosition.y, transform.localPosition.z);
break;
}
}
} }

SnakeHead.cs

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 = ;
public int ylimit = ;
//x轴活动空间不对称问题,对x轴的偏移值
public int xoffset = ;
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(,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 * , y * , );
//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 * , y * , );
}
}
}

FoodMaker.cs

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 = ;
public int length = ;
public Text msgText;
public Text scoreText;
public Text lengthText;
public Image bgImage;
private Color tempColor; void Awake()
{
_instance = this;
} private void Update()
{
switch (score / )
{
case :
ColorUtility.TryParseHtmlString("#CCEEFFFF",out tempColor);
bgImage.color=tempColor;
msgText.text = "阶段" + ;
break;
case :
ColorUtility.TryParseHtmlString("#CCEEFFFF", out tempColor);
bgImage.color = tempColor;
msgText.text = "阶段" + ;
break;
case :
ColorUtility.TryParseHtmlString("#CCFFDBFF", out tempColor);
bgImage.color = tempColor;
msgText.text = "阶段" + ;
break;
case :
ColorUtility.TryParseHtmlString("#EBFFCCFF", out tempColor);
bgImage.color = tempColor;
msgText.text = "阶段" + ;
break;
case :
ColorUtility.TryParseHtmlString("#FFDACCFF", out tempColor);
bgImage.color = tempColor;
msgText.text = "阶段 x";
break;
}
} public void UpdateUI(int s = ,int l = )
{
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 = ;
pauseButton.GetComponent<Image>().sprite = pauseSprites[];
}
else
{
Time.timeScale = ;
pauseButton.GetComponent<Image>().sprite = pauseSprites[];
}
}

  Time.timeScale  传送门

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

  

  

  在onclick()

  解决按键冲突

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

    

  

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

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

 

   接下来实现返回按钮

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

  Home按钮上添加点击事件

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[]; private void Awake()
{
canvas = GameObject.Find("Canvas").transform;
} private void Start()
{
//重复调用
InvokeRepeating("Move",,velocity);
x = ;y = step;
} private void Update()
{
if (Input.GetKeyDown(KeyCode.Space)&&MainUIController.Instance.isPause==false)
{
CancelInvoke();
InvokeRepeating("Move",,velocity - 0.3f);
} if (Input.GetKeyUp(KeyCode.Space) && MainUIController.Instance.isPause == false)
{
CancelInvoke();
InvokeRepeating("Move", , velocity);
} if (Input.GetKey(KeyCode.W) && y!=-step && MainUIController.Instance.isPause == false)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = step;
}
if (Input.GetKey(KeyCode.S) && y!=step && MainUIController.Instance.isPause == false)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = -step;
}
if (Input.GetKey(KeyCode.A) && x!=step && MainUIController.Instance.isPause == false)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = -step;y = ;
}
if (Input.GetKey(KeyCode.D) && x!=-step && MainUIController.Instance.isPause == false)
{
gameObject.transform.localRotation = Quaternion.Euler(, , -);
x = step;y = ;
}
} void Move()
{
//保存下来蛇头移动前的位置
headPos = gameObject.transform.localPosition;
//蛇头向期望位置移动
gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);
if (bodyList.Count > )
{
//由于是双色蛇身,此方法弃用
//将蛇尾移动到蛇头移动前的位置
// bodyList.Last().localPosition = headPos;
//将蛇尾在List中的位置跟新到最前
// bodyList.Insert(0, bodyList.Last());
//溢出List最末尾的蛇尾引用
// bodyList.RemoveAt(bodyList.Count - 1); //从后面开始移动蛇身
for(int i =bodyList.Count-;i>= ;i--)
{
//每一个蛇身都移动到它前面一个
bodyList[i + ].localPosition = bodyList[i].localPosition;
}
//第一个蛇身移动到蛇头移动前的位置
bodyList[].localPosition = headPos; }
} void Grow()
{
int index = (bodyList.Count % == ) ? : ;
GameObject body = Instantiate(bodyPrefab,new Vector3(,,),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(,)<)
{
FoodMaker.Instance.MakeFood(true);
}
else
{
FoodMaker.Instance.MakeFood(false);
}
}
else if(collision.gameObject.CompareTag("Reward"))
{
Destroy(collision.gameObject);
MainUIController.Instance.UpdateUI(Random.Range(,)*);
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+,transform.localPosition.z);
break;
case "Down":
transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y-, transform.localPosition.z);
break;
case "Left":
transform.localPosition = new Vector3(-transform.localPosition.x+,transform.localPosition.y , transform.localPosition.z);
break;
case "Right":
transform.localPosition = new Vector3(-transform.localPosition.x+, transform.localPosition.y, transform.localPosition.z);
break;
}
}
} }

SnakeHead.cs

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 = ;
public int ylimit = ;
//x轴活动空间不对称问题,对x轴的偏移值
public int xoffset = ;
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(,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 * , y * , );
//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 * , y * , );
}
} public void Home()
{
UnityEngine.SceneManagement.SceneManager.LoadScene();
}
}

FoodMaker.cs

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 = ;
public int length = ;
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 / )
{
case :
case :
case :
break;
case :
case :
ColorUtility.TryParseHtmlString("#CCEEFFFF",out tempColor);
bgImage.color=tempColor;
msgText.text = "阶段" + ;
break;
case :
case :
ColorUtility.TryParseHtmlString("#CCEEFFFF", out tempColor);
bgImage.color = tempColor;
msgText.text = "阶段" + ;
break;
case :
case :
ColorUtility.TryParseHtmlString("#CCFFDBFF", out tempColor);
bgImage.color = tempColor;
msgText.text = "阶段" + ;
break;
case :
case :
ColorUtility.TryParseHtmlString("#EBFFCCFF", out tempColor);
bgImage.color = tempColor;
msgText.text = "阶段" + ;
break;
case :
case :
case :
ColorUtility.TryParseHtmlString("#FFDACCFF", out tempColor);
bgImage.color = tempColor;
msgText.text = "阶段 x";
break;
}
} public void UpdateUI(int s = ,int l = )
{
score += s;
length += l;
scoreText.text ="得分:\n"+score;
lengthText.text = "长度\n" + length;
} public void Pause()
{
isPause = !isPause;
if(isPause)
{
Time.timeScale = ;
pauseImage.sprite = pauseSprites[];
}
else
{
Time.timeScale = ;
pauseImage.sprite = pauseSprites[];
}
}
}

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();
}

  

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

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

  

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

  切换场景方法

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

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

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

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

  存储玩家的选择

 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);
}
}

完成换肤与数据读取

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

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

  判断游戏模式

  添加一个模式表示位

    public bool hasBorder = true;

  游戏初始时默认无边界

 void Start()
{
if (PlayerPrefs.GetInt("border", )==)
{
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 + , transform.localPosition.z);
break;
case "Down":
transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y - , transform.localPosition.z);
break;
case "Left":
transform.localPosition = new Vector3(-transform.localPosition.x + , transform.localPosition.y, transform.localPosition.z);
break;
case "Right":
transform.localPosition = new Vector3(-transform.localPosition.x + , transform.localPosition.y, transform.localPosition.z);
break;
}
}

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",) + ",分数" + PlayerPrefs.GetInt("lasts",);
bestText.text = "最好:长度" + PlayerPrefs.GetInt("best1", ) + ",分数" + PlayerPrefs.GetInt("bests",);
} 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", ) == )
{
border.isOn = true;
PlayerPrefs.SetInt("border",);
}
else
{
noborder.isOn = true;
PlayerPrefs.SetInt("border", );
}
} 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",);
}
} public void NoBorderSelected(bool isOn)
{
if (isOn)
{
//自由模式
PlayerPrefs.SetInt("border", );
}
} public void StartGame()
{
UnityEngine.SceneManagement.SceneManager.LoadScene();
}
}

StartUIController.cs

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 = ;
public int length = ;
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", )==)
{
hasBorder = false;
//取消边界上的颜色
foreach(Transform t in bgImage.gameObject.transform)
{
t.gameObject.GetComponent<Image>().enabled = false;
}
}
} private void Update()
{
switch (score / )
{
case :
case :
case :
break;
case :
case :
ColorUtility.TryParseHtmlString("#CCEEFFFF",out tempColor);
bgImage.color=tempColor;
msgText.text = "阶段" + ;
break;
case :
case :
ColorUtility.TryParseHtmlString("#CCEEFFFF", out tempColor);
bgImage.color = tempColor;
msgText.text = "阶段" + ;
break;
case :
case :
ColorUtility.TryParseHtmlString("#CCFFDBFF", out tempColor);
bgImage.color = tempColor;
msgText.text = "阶段" + ;
break;
case :
case :
ColorUtility.TryParseHtmlString("#EBFFCCFF", out tempColor);
bgImage.color = tempColor;
msgText.text = "阶段" + ;
break;
case :
case :
case :
ColorUtility.TryParseHtmlString("#FFDACCFF", out tempColor);
bgImage.color = tempColor;
msgText.text = "阶段 x";
break;
}
} public void UpdateUI(int s = ,int l = )
{
score += s;
length += l;
scoreText.text ="得分:\n"+score;
lengthText.text = "长度\n" + length;
} public void Pause()
{
isPause = !isPause;
if(isPause)
{
Time.timeScale = ;
pauseImage.sprite = pauseSprites[];
}
else
{
Time.timeScale = ;
pauseImage.sprite = pauseSprites[];
}
}
}

MainUIController.cs

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 = ;
public int ylimit = ;
//x轴活动空间不对称问题,对x轴的偏移值
public int xoffset = ;
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(,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 * , y * , );
//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 * , y * , );
}
} public void Home()
{
UnityEngine.SceneManagement.SceneManager.LoadScene();
}
}

FoodMaker.cs

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[]; private void Awake()
{
canvas = GameObject.Find("Canvas").transform;
//通过Resources.Load(string path)方法加载资源;
gameObject.GetComponent<Image>().sprite = Resources.Load<Sprite>(PlayerPrefs.GetString("sh", "sh02"));
bodySprites[] = Resources.Load<Sprite>(PlayerPrefs.GetString("sb01", "sb0201"));
bodySprites[] = Resources.Load<Sprite>(PlayerPrefs.GetString("sb02", "sb0202"));
} private void Start()
{
//重复调用
InvokeRepeating("Move",,velocity);
x = ;y = step;
} private void Update()
{
if (Input.GetKeyDown(KeyCode.Space)&&MainUIController.Instance.isPause==false&&isDie==false)
{
CancelInvoke();
InvokeRepeating("Move",,velocity - 0.3f);
} if (Input.GetKeyUp(KeyCode.Space) && MainUIController.Instance.isPause == false && isDie == false)
{
CancelInvoke();
InvokeRepeating("Move", , velocity);
} if (Input.GetKey(KeyCode.W) && y!=-step && MainUIController.Instance.isPause == false && isDie == false)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = step;
}
if (Input.GetKey(KeyCode.S) && y!=step && MainUIController.Instance.isPause == false && isDie == false)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = -step;
}
if (Input.GetKey(KeyCode.A) && x!=step && MainUIController.Instance.isPause == false && isDie == false)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = -step;y = ;
}
if (Input.GetKey(KeyCode.D) && x!=-step && MainUIController.Instance.isPause == false && isDie == false)
{
gameObject.transform.localRotation = Quaternion.Euler(, , -);
x = step;y = ;
}
} void Move()
{
//保存下来蛇头移动前的位置
headPos = gameObject.transform.localPosition;
//蛇头向期望位置移动
gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);
if (bodyList.Count > )
{
//由于是双色蛇身,此方法弃用
//将蛇尾移动到蛇头移动前的位置
// bodyList.Last().localPosition = headPos;
//将蛇尾在List中的位置跟新到最前
// bodyList.Insert(0, bodyList.Last());
//溢出List最末尾的蛇尾引用
// bodyList.RemoveAt(bodyList.Count - 1); //从后面开始移动蛇身
for(int i =bodyList.Count-;i>= ;i--)
{
//每一个蛇身都移动到它前面一个
bodyList[i + ].localPosition = bodyList[i].localPosition;
}
//第一个蛇身移动到蛇头移动前的位置
bodyList[].localPosition = headPos; }
} void Grow()
{
int index = (bodyList.Count % == ) ? : ;
GameObject body = Instantiate(bodyPrefab,new Vector3(,,),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", )<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();
} private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.CompareTag("Food"))
{
Destroy(collision.gameObject);
MainUIController.Instance.UpdateUI();
Grow();
if (Random.Range(,)<)
{
FoodMaker.Instance.MakeFood(true);
}
else
{
FoodMaker.Instance.MakeFood(false);
}
}
else if(collision.gameObject.CompareTag("Reward"))
{
Destroy(collision.gameObject);
MainUIController.Instance.UpdateUI(Random.Range(,)*);
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 + , transform.localPosition.z);
break;
case "Down":
transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y - , transform.localPosition.z);
break;
case "Left":
transform.localPosition = new Vector3(-transform.localPosition.x + , transform.localPosition.y, transform.localPosition.z);
break;
case "Right":
transform.localPosition = new Vector3(-transform.localPosition.x + , transform.localPosition.y, transform.localPosition.z);
break;
}
}
}
} }

SnakeHead.cs

添加游戏音乐

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

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

    public AudioClip eatClip;
public AudioClip dieClip;

  

void Grow()
{
//播放贪吃蛇变长音乐
AudioSource.PlayClipAtPoint(eatClip,Vector3.zero);
int index = (bodyList.Count % == ) ? : ;
GameObject body = Instantiate(bodyPrefab,new Vector3(,,),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", )<MainUIController.Instance.score)
{
//将当前游戏长度和分数记录到best1和bests当中
PlayerPrefs.SetInt("best1", MainUIController.Instance.length);
PlayerPrefs.SetInt("bests", MainUIController.Instance.score);
}
StartCoroutine(GameOver(1.0f));
}

  

游戏源代码

  控制蛇和食物脚本

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[]; private void Awake()
{
canvas = GameObject.Find("Canvas").transform;
//通过Resources.Load(string path)方法加载资源;
gameObject.GetComponent<Image>().sprite = Resources.Load<Sprite>(PlayerPrefs.GetString("sh", "sh02"));
bodySprites[] = Resources.Load<Sprite>(PlayerPrefs.GetString("sb01", "sb0201"));
bodySprites[] = Resources.Load<Sprite>(PlayerPrefs.GetString("sb02", "sb0202"));
} private void Start()
{
//重复调用
InvokeRepeating("Move",,velocity);
x = ;y = step;
} private void Update()
{
if (Input.GetKeyDown(KeyCode.Space)&&MainUIController.Instance.isPause==false&&isDie==false)
{
CancelInvoke();
InvokeRepeating("Move",,velocity - 0.3f);
} if (Input.GetKeyUp(KeyCode.Space) && MainUIController.Instance.isPause == false && isDie == false)
{
CancelInvoke();
InvokeRepeating("Move", , velocity);
} if (Input.GetKey(KeyCode.W) && y!=-step && MainUIController.Instance.isPause == false && isDie == false)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = step;
}
if (Input.GetKey(KeyCode.S) && y!=step && MainUIController.Instance.isPause == false && isDie == false)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = ;y = -step;
}
if (Input.GetKey(KeyCode.A) && x!=step && MainUIController.Instance.isPause == false && isDie == false)
{
gameObject.transform.localRotation = Quaternion.Euler(, , );
x = -step;y = ;
}
if (Input.GetKey(KeyCode.D) && x!=-step && MainUIController.Instance.isPause == false && isDie == false)
{
gameObject.transform.localRotation = Quaternion.Euler(, , -);
x = step;y = ;
}
} void Move()
{
//保存下来蛇头移动前的位置
headPos = gameObject.transform.localPosition;
//蛇头向期望位置移动
gameObject.transform.localPosition = new Vector3(headPos.x+x,headPos.y+y,headPos.z);
if (bodyList.Count > )
{
//由于是双色蛇身,此方法弃用
//将蛇尾移动到蛇头移动前的位置
// bodyList.Last().localPosition = headPos;
//将蛇尾在List中的位置跟新到最前
// bodyList.Insert(0, bodyList.Last());
//溢出List最末尾的蛇尾引用
// bodyList.RemoveAt(bodyList.Count - 1); //从后面开始移动蛇身
for(int i =bodyList.Count-;i>= ;i--)
{
//每一个蛇身都移动到它前面一个
bodyList[i + ].localPosition = bodyList[i].localPosition;
}
//第一个蛇身移动到蛇头移动前的位置
bodyList[].localPosition = headPos; }
} void Grow()
{
//播放贪吃蛇变长音乐
AudioSource.PlayClipAtPoint(eatClip,Vector3.zero);
int index = (bodyList.Count % == ) ? : ;
GameObject body = Instantiate(bodyPrefab,new Vector3(,,),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", )<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();
} private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.gameObject.CompareTag("Food"))
{
Destroy(collision.gameObject);
MainUIController.Instance.UpdateUI();
Grow();
if (Random.Range(,)<)
{
FoodMaker.Instance.MakeFood(true);
}
else
{
FoodMaker.Instance.MakeFood(false);
}
}
else if(collision.gameObject.CompareTag("Reward"))
{
Destroy(collision.gameObject);
MainUIController.Instance.UpdateUI(Random.Range(,)*);
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 + , transform.localPosition.z);
break;
case "Down":
transform.localPosition = new Vector3(transform.localPosition.x, -transform.localPosition.y - , transform.localPosition.z);
break;
case "Left":
transform.localPosition = new Vector3(-transform.localPosition.x + , transform.localPosition.y, transform.localPosition.z);
break;
case "Right":
transform.localPosition = new Vector3(-transform.localPosition.x + , transform.localPosition.y, transform.localPosition.z);
break;
}
}
}
} }

SnakeHead.cs

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 = ;
public int ylimit = ;
//x轴活动空间不对称问题,对x轴的偏移值
public int xoffset = ;
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(,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 * , y * , );
//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 * , y * , );
}
} public void Home()
{
UnityEngine.SceneManagement.SceneManager.LoadScene();
}
}

FoodMaker.cs

  场景UI控制脚本 

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 = ;
public int length = ;
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", )==)
{
hasBorder = false;
//取消边界上的颜色
foreach(Transform t in bgImage.gameObject.transform)
{
t.gameObject.GetComponent<Image>().enabled = false;
}
}
} private void Update()
{
switch (score / )
{
case :
case :
case :
break;
case :
case :
ColorUtility.TryParseHtmlString("#CCEEFFFF",out tempColor);
bgImage.color=tempColor;
msgText.text = "阶段" + ;
break;
case :
case :
ColorUtility.TryParseHtmlString("#CCEEFFFF", out tempColor);
bgImage.color = tempColor;
msgText.text = "阶段" + ;
break;
case :
case :
ColorUtility.TryParseHtmlString("#CCFFDBFF", out tempColor);
bgImage.color = tempColor;
msgText.text = "阶段" + ;
break;
case :
case :
ColorUtility.TryParseHtmlString("#EBFFCCFF", out tempColor);
bgImage.color = tempColor;
msgText.text = "阶段" + ;
break;
case :
case :
case :
ColorUtility.TryParseHtmlString("#FFDACCFF", out tempColor);
bgImage.color = tempColor;
msgText.text = "阶段 x";
break;
}
} public void UpdateUI(int s = ,int l = )
{
score += s;
length += l;
scoreText.text ="得分:\n"+score;
lengthText.text = "长度\n" + length;
} public void Pause()
{
isPause = !isPause;
if(isPause)
{
Time.timeScale = ;
pauseImage.sprite = pauseSprites[];
}
else
{
Time.timeScale = ;
pauseImage.sprite = pauseSprites[];
}
}
}

MainUIController.cs

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",) + ",分数" + PlayerPrefs.GetInt("lasts",);
bestText.text = "最好:长度" + PlayerPrefs.GetInt("best1", ) + ",分数" + PlayerPrefs.GetInt("bests",);
} 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", ) == )
{
border.isOn = true;
PlayerPrefs.SetInt("border",);
}
else
{
noborder.isOn = true;
PlayerPrefs.SetInt("border", );
}
} 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",);
}
} public void NoBorderSelected(bool isOn)
{
if (isOn)
{
//自由模式
PlayerPrefs.SetInt("border", );
}
} public void StartGame()
{
UnityEngine.SceneManagement.SceneManager.LoadScene();
}
}

StartUIController.cs

最新文章

  1. 关于包含pom.xml的开源项目如何导入
  2. 用rlwrap使sqlplus可以上下翻页
  3. request.querystring和request.form、session的区别
  4. CSS属性之 -- overflow
  5. 应用内存优化之OnLowMemory&amp;OnTrimMemory
  6. VPN DNS leak 问题的解决
  7. 你真的会用 SDWebImage?
  8. centos 网站目录权限参考
  9. 关于ASIHTTPRequest连续请求,并发连续,间隔时间很小崩溃问题
  10. SQL Server中日志
  11. MySQL DATE_FORMAT
  12. 用开源的 ffmpeg 实现屏幕录像机
  13. Class.isAssignableFrom与instanceof的区别
  14. Jetson TX1 install py-faster-rcnn
  15. 自己总结的C#编码规范--2.命名选择篇
  16. Http协议的理解
  17. python 多线程 并发socket实例
  18. linux内核环形缓冲区【转】
  19. 使用python来搞定redis的订阅功能
  20. SpringBoot 中使用redis以及redisTemplate

热门文章

  1. 使用Python基于VGG/CTPN/CRNN的自然场景文字方向检测/区域检测/不定长OCR识别
  2. DIj
  3. luogu题解 P1462 【通往奥格瑞玛的道路】二分+spfa
  4. React 长列表修改时避免全体渲染
  5. TCP/IP模型层次结构
  6. python 3.8 新特性
  7. python视频学习笔记4(函数)
  8. rabbitmq一键部署脚本
  9. git用ssh方式下载和提交代码
  10. docker compose无法解析正确的版本