Unity-3d小游戏开发-----走迷宫

Posted 崎月xy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity-3d小游戏开发-----走迷宫相关的知识,希望对你有一定的参考价值。

本人是在学习完c,c++,数据结构算法,操作系统网络这些基础的课程之后,打算学习自己喜欢的游戏开发方向的东西,然后在B站上自学了几天unity,用到unity的触发器,碰撞,刚体,以及一个简单的ui界面,但是本人目前没有c#的学习经验,但是拿c++的经验也能写出一些基础的游戏脚本,这里的参考书籍是《新印象--unity2020游戏开发基础与实战》,适合有一些编程基础的人来观看。

我将从unity的新建项目开始来一步一步的完成这个小游戏

环境为unity2021.3.16 编译器为VS2019

目录

 小游戏拆解

场地的搭建

角色的移动

玩家与墙体的碰撞检测

玩家吃金币的实现

金币吃完解锁大门

 玩家达到指定点结束游戏胜利

角色血量与UI的绑定

项目文件


 小游戏拆解

首先这个迷宫小游戏大致分为几个逻辑模块

首先问题是我们如何让角色移动起来

还有角色与墙体的碰撞检测

角色吃金币的实现

金币吃完解锁大门

玩家达到指定点结束游戏胜利

角色血量与UI的绑定

接下来将分为这些模块来将这个简单的小游戏来逐步的拆解

场地的搭建

 

先新建一个3d项目

 就会得到了这个界面,这就是unity的基础界面

 我们在这里改成2*3格式

 然后我们就可以开始开发了

我们在右键菜单栏里面新建一个平面

然后在场景窗口选中调整缩放

 这样我们就可以把这个平面成为自己的迷宫地面了

然后我们在项目栏新建一个材质,并且调整一个自己喜欢的颜色

 

 然后将新建的材质拖到平面上进行绑定

 然后接下来我们来为迷宫的墙体制造,就是将立方体选装缩放成为墙面,这里就直接略过创建过程了

 这样就将迷宫的基本框架搭建完成了,接下来制作金币的形状,就是将圆柱体缩放选装,并且添加上金色的材质

 然后创建一个平面作为我们的终点,一个门作为阻碍,并且创建一个球体作为我们的玩家

 这样我们就将游戏里面的基本地形搭建完成了。

角色的移动

实现角色的移动有很多种方法:角色控制器,或者调整Transform组件,这里选装用刚体组件控制球体的移动

我们为球体玩家添加rigidbody组件,并且新建一个c#脚本来控制方向。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMove : MonoBehaviour

    //设置默认移动速度
    public float player_speed = 4.0f;
    //设置玩家血量
    public int health = 3;
    //设置玩家刚体组件
    private Rigidbody rBody;
    // Start is called before the first frame update
    void Start()
    
        //初始化玩家刚体组件
        rBody = GetComponent<Rigidbody>();
    

    // Update is called once per frame
    void Update()
    
        //获取玩家水平移动方向
        float horizontal = Input.GetAxis("Horizontal");
        float vertical = Input.GetAxis("Vertical");
        //将两个方向合成一个向量 0 是因为我们不需要y轴移动
        Vector3 dir = new Vector3(horizontal, 0, vertical);
        if (dir != Vector3.zero)
        
            //将移动方向传给刚体组件
            rBody.velocity = dir * player_speed;
        

    

 

此时我们就可以将玩家成功移动了 

玩家与墙体的碰撞检测

 首先我们先选中迷宫的全部墙体,并且为全部的墙体添加Wall标签

 然后添加碰撞检测的功能

 我们可以看到,当碰撞超过三次,玩家就销毁自身了

玩家吃金币的实现

首先我们玩家需要吃金币而不是碰撞到金币,所以我们就需要让金币成为一个触发器,当金币被玩家触发,销毁自身,达到吃金币的效果。

首先我们为玩家添加Player标签

然后编写金币的脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class gold : MonoBehaviour

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

    // Update is called once per frame
    void Update()
    
        
    
    //unity提供的进入触发函数
    private void OnTriggerEnter(Collider other)
    
        if (other.tag == "Player")
        
            //检测到玩家的触发,销毁自身
            Destroy(gameObject);
        
    

并且将金币设为触发器

 

 我们看到这就成功将金币吃掉了

接下来我们为金币添加一个自动旋转的功能

可以看到,我们要是想让金币旋转,需要让金币绕着x轴旋转

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class gold : MonoBehaviour

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

    // Update is called once per frame
    void Update()
    
        transform.Rotate(Vector3.right * 90 * Time.deltaTime);
    
    //unity提供的进入触发函数
    private void OnTriggerEnter(Collider other)
    
        if (other.tag == "Player")
        
            //检测到玩家的触发,销毁自身
            Destroy(gameObject);
        
    

这样金币的基本功能,就基本实现了。

金币吃完解锁大门

 这个实现我是利用一个空的游戏对象,作为一个金币管理器,当三个金币成为金币管理器的子物体,当金币管理器成为金币的父对象,然后检测这个金币管理器的子物体个数,当子物体为0时,销毁门。

 创建一个空对象,作为金币管理器

将三个金币作为管理器的子物体,然后新建一个c#脚本来实现开门的逻辑

我们创建一个共有的对象,然后保存脚本

 这样我们就可以在unity界面看到一个游戏对象选项,我们拖动door绑定到游戏对象上

 

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class opendoor : MonoBehaviour

    public GameObject door;
    // Start is called before the first frame update
    void Start()
    
        
    

    // Update is called once per frame
    void Update()
    
        //当子对象为0时,销毁大门,然后销毁自身
        if (transform.childCount <= 0)
        
            Destroy(door);
            Destroy(gameObject);
        
    

 这样我们就实现吃完全部金币开门的功能了

 玩家达到指定点结束游戏胜利

这里我们还是来用触发器实现

 我们将结束点这个平面设置为凸面,和触发器,并且新建一个脚本来实现控制游戏胜利

我们先新建一个ui画布,并且设置为2d视图

 然后我们右键画布-》ui-》文本,并且导入Tmp的两个包

 

 修改颜色和字体,我们可以,看到胜利显示在我们的游戏画面上,我们将这个字体设置为不激活状态,这样就不会直接显示到现在的界面上,当玩家走到指定位置我们再将文本激活,显示到玩家的UI上

 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class end : MonoBehaviour

    //得到文本
    public GameObject txt;
    // Start is called before the first frame update
    void Start()
    
        
    

    // Update is called once per frame
    void Update()
    
        
    
    private void OnTriggerEnter(Collider other)
    
        if (other.tag == "Player")
        
            //设置激活
            txt.SetActive(true);
            Destroy(gameObject);
        

    

 

 

 这样我们可以看到游戏就正常结束了。

这样其实基本的游戏功能就实现了。

角色血量与UI的绑定

我们需要将血量也显示到ui上,接下来同样在画布上新建一个文本

拖到画布的左上角,设置好文本和颜色

然后新建一个脚本

拿到我们的玩家物体,和自己的文本,然后获取玩家的血量显示出来

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.UI;
using TMPro;


public class UIhealth : MonoBehaviour

    public GameObject player;
    public TMP_Text text;
    // Start is called before the first frame update
    void Start()
    
        text = GetComponent<TMP_Text>();
    

    // Update is called once per frame
    void Update()
    
        //获取玩家血量
        int hp = player.GetComponent<PlayerMove>().health;
        //修改显示文本
        text.text = "health:" + hp;
    

 

 

 

这样我们可以看到血量成功显示到UI上了

然后我们把主摄像机的位置调整下,就可以成功完成整个游戏了

 

选中主摄像机,按ctrl+shift+f,移动到场景所显示的位置

 并且将投影设置为正交,这样就可以让我们的观看更加的轻松

这样我们整个项目就完成了开发

项目文件

链接:https://pan.baidu.com/s/1rBvYlLo5l2NNZPopze3rkQ 
提取码:jina

感谢您能看到这里,这是我初学unity以来的第一个项目,您也可以尝试自己添加其他元素

 

兔年之兔子走迷宫 用一个小游戏对回溯法进行实现 | C++

第六章 回溯法


::: hljs-center

目录

第六章 回溯法

●前言

●一、回溯法是什么?

1.简要介绍

●二、回溯法经典案例——兔子走迷宫游戏

1.具体情况

2.代码展示(C++)

3.结果展示

●总结

:::

前言

简单的来说,算法就是用计算机程序代码来实现数学思想的一种方法。学习算法就是为了了解它们在计算机中如何演算,以及在当今的信息时代,它们是如何在各个层面上影响我们的日常生活的,从而提高我们的逻辑思维能力和处理实际问题的能力。善用算法、巧用算法,是培养程序设计逻辑的重中之重,许多实际的问题都可用多个可行的算法来解决, 但是要从中找出最优的解决算法却是一项挑战。


一、回溯法是什么?

1.简要介绍

回溯法是枚举法的一种,它是一种可以找出所有解的一般性算法。同时为了避免枚举出现不正确的数值,发现错误值就停止向下一层运行,而是回溯到上一层。为了去减短时间和提高程序代码的执行效率,回溯法一般是一种走不通就退回另寻蹊径的方法。它的特点是在搜索过程中去寻找问题的解,发现不满足的答案就去回溯,从而去避免无效搜索。

二、回溯法经典案例——兔子走迷宫游戏

1.具体情况

假如有一只兔子,我们去把它放到一个没有盖子的大迷宫盒中的起点,迷宫内有很多墙,从而使得大部分路径都被挡住而不能前行。兔子需要采用一种试错的方式去尝试走出迷宫,并且兔子需要在每次走错路时把走过的路记录下来,避免再次重复,直到最终到达终点。即①一次只能走一格;②遇到墙无法前行时回退一步去重新判断;③走过的路不会再走第二次; 在程序中我们仿真迷宫的地图就用二维数组来抽象表示,用0去表示墙,用1表示通路。从而去创建一个12✖12大小的迷宫地图。如下图所示: 兔子将会从起点maze[1][1]进入,从终点maze[9][10]出来,兔子当前的位置我们用maze[x][y]去表示。兔子在迷宫中可以选择的方向有四个,东、南、西、北。但并非每个位置此刻的兔子都可以去任意移动,需根据兔子所处在迷宫中的具体情况而定。从而我们可去创建一个老鼠移动的方位图。如下图所示: 在该过程中我们将会用链表去对兔子走过的路径进行记录,并且将兔子走过的路径标记为2,再将其放入堆栈中,再去进行下一个方向的判断。由于每次每次新加入堆栈中的位置都会在其顶端,因此堆栈顶端指针指向的编号便是当前迷宫中兔子的位置。我们会将主要的算法写到类模块中,它主要用于去判断在当前位置的四个方位上是否存在前进的表格。若找到可前进的方格,则将该方格的编号记录到堆栈并且移动,反之则回溯进行重新的判断。

2.代码展示(C++)

用程序代码去实现具体情况中的兔子走迷宫游戏。

#include<iostream>
using namespace std;
#define north maze[x-1][y]   //北
#define south maze[x+1][y]   //南
#define west maze[x][y-1]    //西
#define east maze[x][y+1]	 //东
int maze[12][12] =  0,0,0,0,0,0,0,0,0,0,0,0,
					 0,1,1,1,0,0,0,0,0,0,0,0,
					 0,0,0,1,0,0,1,1,1,1,0,0,
					 0,0,0,1,0,0,1,0,0,1,0,0,
					 0,0,0,1,1,1,1,0,0,1,0,0,
					 0,0,0,1,0,0,1,0,0,1,0,0,
					 0,0,0,1,0,0,1,0,0,1,0,0,
					 0,0,0,1,0,0,1,0,0,1,0,0,
					 0,0,0,0,0,0,1,0,0,1,0,0,
					 0,0,1,1,1,1,1,1,0,1,1,0,
					 0,0,1,0,0,0,0,0,0,0,0,0,
					 0,0,0,0,0,0,0,0,0,0,0,0 ;  //二维数组迷宫图,0表示墙,1表示通路
const int exitx = 9, exity = 10;   //出口端在数组迷宫中的位置,9行10列
 
//链表的定义及其记录使用
struct list 
	int x, y;
	struct list* next;
;
typedef struct list node;
typedef node* link;
link push(link stack,int x,int y)

	link newnode;
	newnode = new node;
	if (!newnode)
	
		return NULL;
	
	newnode->x = x;
	newnode->y = y;
	newnode->next = stack;
	stack = newnode;
	return stack;

link pop(link stack, int *x, int *y)

	link top;
	if (stack != NULL)
	
		top = stack;
		stack=stack->next;
		*x= top->x;
		*y = top->y;
		delete top;
		return stack;
	
	else
	
		*x = -1;
	
	return stack;

//
 
int checkexit(int x,int y)  //检查是否到达终点

	if (x == exitx && y == exity)
		return 1;
	else
		return 0;

 
class maze_data 
public:
	int x;
	int y;
	void walk_judgement()
	
		link path = NULL;   //初始化路径
		while (x <= exitx && y <= exity)   //while循环中进行东南西北四个方位移动的判断
		
			maze[x][y] = 2;
			if (north == 1)  //上一格可走
			
				x--;  //往上走
				path = push(path, x, y);  //加入方格编号到对堆栈
			
			else if (south == 1)  //下一个可走
			
				x++;   //往下走
				path = push(path, x, y); //加入方格编号到对堆栈
			
			else if (west == 1)   //左一格可走
			
				y--;   //往左走
				path = push(path, x, y); //加入方格编号到对堆栈
			
			else if (east == 1)    //右一格可走
			
				y++;   //往右走
				path = push(path, x, y); //加入方格编号到对堆栈
			
			else if (checkexit(x, y) == 1)  //如果判断到已经到达终点,从而跳出循环
				break; 
			else    //记录走过的位置
			
				maze[x][y] = 2;
				path = pop(path, &x, &y);
			
		
	
;
void text1()

	cout << "-----------------------" << endl;
	for (int i = 0; i < 12; i++)
	
		for (int j = 0; j < 12; j++)
		
			cout << maze[i][j] << " ";
		
		cout << endl;
	
	cout << "-----------------------" << endl;

void text2()

	maze_data md;
	md.x = 1;
	md.y = 1;
	md.walk_judgement();

int main()

	text1();  //输出初始的迷宫矩阵
	text2();  
	text1();  //输出最终老鼠走过路径的迷宫矩阵

3.结果展示

(图一) (图二)


总结

在以上我们通过一个兔子走迷宫游戏案例,对回溯法进行了实现。其实回溯法应该很广泛的运用到我们的程序代码中,它是一种很好的算法编程思想。大家也可以对我上面的代码进行二次修改,从而去实现一个更大的迷宫地图、更复杂路径和过程的迷宫小游戏。今天刚好是大年除夕,博主在这里给大家拜年了!祝福大家阖家欢乐,兔年大吉!事业“兔”飞猛进,财富“兔”然斗增!身体蹦蹦跳跳健康平安。

以上是关于Unity-3d小游戏开发-----走迷宫的主要内容,如果未能解决你的问题,请参考以下文章

Unity 3d游戏开发者该掌握哪些内容?

游戏开发者眼中的Unity 3D网页游戏测评报告

游戏开发人员眼中的Unity 3D网页游戏測评报告

Android 和 Unity 3D 游戏开发

[Unity3D]Unity3D游戏开发之从Unity3D到Eclipse

[Unity3D]Unity3D游戏开发之异步记载场景并实现进度条读取效果