目录
前言
一、整体设计思路
二、蛇体部分
2.1 蛇头(模仿传统贪吃蛇)
2.2 蛇身
2.3 贪吃蛇(改进版)
三、食物部分
3.1 旋转
3.2 触发器
3.3 生成食物
四、墙体部分
4.1 提供环境
五、胜利和失败的判定
5.1 屏幕显示分数
5.2 游戏胜利
5.3 游戏失败
六、界面设计
6.1 开始界面
6.2 结果界面(胜利/失败)
6.3 分数显示
6.4 退出界面
前言
最近在学习unity,计划做一个3D的贪吃蛇的小游戏,利用这个小游戏锻炼自己使用软件的熟练度。
一、整体设计思路
简单起见,并不进行建模美化操作,以直径为1的球体代替蛇头,直径为0.5的球体代替蛇身,用旋转的立方体代替食物,需要实现的功能有:
1. 蛇体部分
- 蛇头:移动
- 蛇身:增长、跟随蛇身运动
- 视角:跟随
2. 食物部分
- 旋转
- 触发器(接触后销毁,并生成一个新的食物)
- 食物出现在空间内的位置随机
3. 墙体部分
- 提供食物生成的封闭空间
4. 胜利和失败的判定
- 屏幕显示分数
- 分数到达10即为胜利,可以选择继续游戏或结束本局游戏
- 碰触墙壁或自身身体即为游戏失败,可以选择重新开始或退出游戏
5. 界面设计
- 开始界面
- 结果界面(胜利/失败)
- 分数显示
- 退出界面
二、蛇体部分
2.1 蛇头(模仿传统贪吃蛇)
蛇头的移动的实现思路是:获取当前相机的前向方向向量,通过按键检测控制移动方向,用一个Vector3 movement向量存储移动的增量,不断增加即可。
相机可以通过鼠标右键进行控制,具体控制代码见另一篇文章:
[Unity3D] 视角旋转学习笔记https://blog.csdn.net/The___sky_/article/details/130249220?spm=1001.2014.3001.5502
//蛇头移动+相机跟随
private void Move()
{
// 跟随相机方向一起转动
cameraRotation = Camera.main.transform.rotation;
BodyNode.rotation = cameraRotation;
SnakeRotation = cameraRotation;
Snake.transform.rotation = SnakeRotation;
// 获取当前相机的前向方向向量
Vector3 cameraForward = Camera.main.transform.forward;
cameraForward = cameraForward.normalized;
Vector3 cameraRight = Camera.main.transform.right;
cameraRight = cameraRight.normalized;
// 计算移动方向
Vector3 moveDirection = cameraForward * vertical + cameraRight * horizontal;
Vector3 movement = moveDirection * moveSpeed * deltaTime;
if (Input.GetKeyDown(KeyCode.W))
{
movement = Vector3.forward;
}
else if (Input.GetKeyDown(KeyCode.A))
{
movement = Vector3.left;
}
else if (Input.GetKeyDown(KeyCode.S))
{
movement = Vector3.back;
}
else if (Input.GetKeyDown(KeyCode.D))
{
movement = Vector3.right;
}
else if (Input.GetKeyDown(KeyCode.U))
{
movement = Vector3.up;
}
else if (Input.GetKeyDown(KeyCode.P))
{
movement = Vector3.down;
}
Snake.transform.position += movement;
// 更新蛇身位置和旋转信息
for (int i = 0; i < bodyList.Count; i++)
{
bodyPositions[i] = bodyList[i].transform.position;
bodyRotations[i] = bodyList[i].transform.rotation;
}
}
2.2 蛇身
蛇身的增长,跟随蛇身移动
private void Start()
{
// 尝试使用动画后的注释
//bodyList = new List<Rigidbody>();
//bodyList.Add(BodyNode);
//bodyPositions = new Vector3[bodyList.Count];
//bodyRotations = new Quaternion[bodyList.Count];
CreateFood();
}
void LateUpdate()
{
bodyList[0].position += movement;
// 更新蛇身位置和旋转信息
for (int i = 0; i < bodyList.Count; i++)
{
bodyPositions[i] = bodyList[i].transform.position;
bodyRotations[i] = bodyList[i].transform.rotation;
}
}
private void CreateBody()
{
// 尝试使用动画后的注释
Rigidbody newBody = Instantiate(BodyPrefabs, bodyList[bodyList.Count - 1].transform.position, Quaternion.identity);
bodyList.Add(newBody);
bodyPositions = new Vector3[bodyList.Count];
bodyRotations = new Quaternion[bodyList.Count];
}
2.3 贪吃蛇(改进版)
在改进版中,对食物和蛇体导入了外部的3D模型和动画,对场景进行了一定程度的美化,在原有的贪吃蛇的规则上进行了如下改变:
- 吃到食物后不会增长身体,而是体型增大。
- 由于导入的外部模型和动画,故而无法实现自己碰到自己身体的条件,所以失败条件改为触碰到墙壁即判定为游戏失败。
在改进版的贪吃蛇中,对蛇体的控制是另外的代码,如果大家感兴趣可以私信我,这里就不做展示了。
三、食物部分
3.1 旋转
新建一个脚本,作用对象是食物,将Update中的代码进行修改。
void Update()
{
//Vector3.up = (0,1,0)
//Space.World:相对于世界坐标系
//即绕y轴旋转
transform.Rotate(Vector3.up, Space.World);
}
3.2 触发器
按照2D贪吃蛇的逻辑,食物在被蛇头接触后应对其进行销毁,并生成一个新的食物。
注意,如果想要某个游戏物体能够触发触发器,该游戏物体需要带有刚体(Rigidbody)组件。
首先将其作为触发器,而不是碰撞器,应勾选Is Trigger.
对其新建一个标签,命名为Food,方便后续检测碰撞对象
在OnTriggerEnter中进行碰撞对象的销毁和新食物的创建(CreateFood)
private void OnTriggerEnter(Collider other)
{
//检测触发器的对象是否是食物
if (other.tag == ("Food"))
{
//是食物则销毁当前碰撞的游戏物体
Destroy(other.gameObject);
CreateFood();
}
}
3.3 生成食物
食物出现在空间内的随机位置分为三步:
- 将预先设置好的食物预制体实例化
- 生成x,y,z的随机数
- 将生成的随机数作为新生成的食物的位置参数
void CreateFood()
{
//将预制体实例化
GameObject Foods = Instantiate(FoodPrefabs);
//随机生成位置
int x = Random.Range(-9, 9);
int y = Random.Range(1, 19);
int z = Random.Range(-9, 9);
Foods.transform.position = new Vector3(x, y, z);
}
四、墙体部分
4.1 提供环境
提供食物生成的封闭空间
设置一个预制体,对其进行整体操作。
当前游戏设计中游戏空间为矩形大小,规格为20*20*20,坐标为:x:[-10,10],y:[0,20],z:[-10,10],因此在生成食物时也需要注意不要让食物产生在无法到达的边界。
五、胜利和失败的判定
5.1 屏幕显示分数
新建Text控件,用来显示当前分数。
// 分数
private int Score;
public Text ScoreText;
// 分数变化
void ScoreChange()
{
Score++;
ScoreText.text = "Score:" + Score;
}
5.2 游戏胜利
分数到达10即为胜利。
新建Text控件,用来显示当前分数,一个用来显示结果,显示结果的Text先不给予显示。
public GameObject Result;
public Text ResultText;
// 胜利界面
void WinInterface()
{
Result.SetActive(true);
if (Score == 10)
{
ResultText.text = "You win!!!";
}
}
5.3 游戏失败
碰触墙壁或自身身体即为游戏失败,键盘不再可以继续操控小球运动。
private void Update()
{
switch(InterfaceFlag)
{
// 胜利
case 1:
WinnerInterface();
break;
// 失败
case 2:
GameOverInterface();
Direction = 0;
break;
// 默认
default:
break;
}
if(InterfaceFlag == 0)
{
Move();
}
}
// 失败界面
void GameOverInterface()
{
Result.SetActive(true);
ResultText.text = "Game Over!";
}
可以选择重新开始或退出游戏
六、界面设计
6.1 开始界面
开始界面和界面的跳转建议读下面这篇文章,写的非常详细,一步一步来就好了,我做的非常简略,就不在这里献丑啦!
unity——通过点击按钮进行场景切换
6.2 结果界面(胜利/失败)
结果界面通过一个公用的Text控件实现,根据不同的游戏结果呈现出不同的文字。
// 胜利界面
void WinnerInterface()
{
// 激活控件
Result.SetActive(true);
ResultText.text = "You win!!!";
// 停止所有
Time.timeScale = 0;
}
// 失败界面
void GameOverInterface()
{
Result.SetActive(true);
ResultText.text = "Game Over!";
// 停止所有
Time.timeScale = 0;
}
6.3 分数显示
将分数放在右上角,用Text控件实现
6.4 退出界面
将EscInterface放在Update()中,通过GetKeyDown检测Esc键是否按下。文章来源:https://www.toymoban.com/news/detail-494413.html
public GameObject Menu;
[SerializeField] private bool MenuKeys = true;
// Esc界面
void EscInterface()
{
if (MenuKeys)
{
if (Input.GetKeyDown(KeyCode.Escape))
{
Menu.SetActive(true);
MenuKeys = false;
Time.timeScale = 0;
}
}
else if (Input.GetKeyDown(KeyCode.Escape))
{
Menu.SetActive(false);
MenuKeys = true;
Time.timeScale = 1;
}
}
关闭程序可以用下行代码文章来源地址https://www.toymoban.com/news/detail-494413.html
public void ExitGame()
{
Application.Quit();
}
到了这里,关于[Unity3D] 3D贪吃蛇的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!