- 贪吃蛇的原理就是使用链表来控制每一个蛇身节点的移动,每个节点的移动都是上一个节点之前移动过的位置.
看图:
最终效果图:
1 首先用一个Sphere做蛇头,上面挂载着SnakeMove,他控制着自己以及第一个节点的移动,第一个节点也就是我们这里的mTop,然后再建立一个Cube作为预制体,上面挂载BodyScript,他掌管着下一个节点(next)的移动,当按住空格键的时候,生成这个预制体,他就成了尾节点(mTail),之前的mTail被替代,mTail负责好了下一个,这样推理下去,之后生成的每一个他都会自动管理要怎样移动了~(具体的还是看代码和注释吧)
2 代码如下:
SnakeMove
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SnakeMove : MonoBehaviour
{
private float mSpeed = 1.0f;
private Vector3 mDir;
private float mTime = 0.4f;
//第一个蛇身节点
public GameObject mCube;
//作为蛇身的第一个节点
public BodyScript mTop;
//作为蛇身的最后一个节点
public BodyScript mTail;
//储存上一个节点的位置
private Vector3 mPos;
public Color RandomColor()
{
//随机颜色的RGB值。即刻得到一个随机的颜色
float r = Random.Range(0f, 1f);
float g = Random.Range(0f, 1f);
float b = Random.Range(0f, 1f);
Color color = new Color(r, g, b);
return color;
}
void Start()
{
mDir = Vector3.forward;
}
void Update()
{
//保证一次性移动一个单位的距离
if (mTime > 0)
{
mTime -= Time.deltaTime;
if (mTime < 0)
{
Move();
mTime = 0.4f;
}
}
//上下左右只改变方向
if (Input.GetKeyDown(KeyCode.W))
{
mDir = Vector3.forward;
}
if (Input.GetKeyDown(KeyCode.S))
{
mDir = Vector3.back;
}
if (Input.GetKeyDown(KeyCode.A))
{
mDir = Vector3.left;
}
if (Input.GetKeyDown(KeyCode.D))
{
mDir = Vector3.right;
}
if (Input.GetKeyDown(KeyCode.Space))
{
//实例化一个节点
GameObject newBody = Instantiate(mCube, new Vector3(1000, 0, 0), Quaternion.identity) as GameObject;
newBody.GetComponent<MeshRenderer>().material.color = RandomColor();
//第一个节点生成
if (mTop == null)
{
//第一个节点
mTop = newBody.GetComponent<BodyScript>();
//将指针指向蛇身的第一节(因为此时只有一个节点)
mTail = mTop;
}
//非第一次生成的情况
else
{
//尾节点(当前最后一个节点)的下一个节点指向新生成的节点
mTail.next = newBody.GetComponent<BodyScript>();
//尾节点指向新生成的节点
mTail = mTail.next;
}
}
}
void Move()
{
//记录移动前的位置
mPos = this.transform.position;
//蛇头向前移动
this.transform.position += mDir * mSpeed;
//让第一个节点跟着蛇头移动
if (mTop != null)
mTop.Move(mPos);
}
}
BodyScript
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BodyScript : MonoBehaviour {
//第二个节点(第一个节点的下一个)
public BodyScript next;
//用来接收物体的临时位置
private Vector3 myPos;
public void Move(Vector3 pos)
{
myPos = this.transform.position;
this.transform.position = pos;
//如果当前cube还有子节点,不是蛇尾最后一节
if (next != null)
{
//加上蛇头的第三个节点开始以后的蛇身移动到上一个节点的位置
next.Move(myPos);
}
}
}