智能巡逻兵小游戏
作业要求
- 游戏设计要求:智能巡逻兵
- 创建一个地图和若干巡逻兵(使用动画);
- 每个巡逻兵走一个3~5个边的凸多边型,位置数据是相对地址。即每次确定下一个目标位置,用自己当前位置为原点计算;
- 巡逻兵碰撞到障碍物,则会自动选下一个点为目标;
- 巡逻兵在设定范围内感知到玩家,会自动追击玩家;
- 失去玩家目标后,继续巡逻;
- 计分:玩家每次甩掉一个巡逻兵计一分,与巡逻兵碰撞游戏结束;
- 程序设计要求:
- 必须使用订阅与发布模式传消息
- Subject(:OnLostGoal)、Publisher、Subscriber
- 工厂模式生产巡逻兵
- 必须使用订阅与发布模式传消息
项目文档 - 智能巡逻兵
一、游戏规则
开始游戏后,玩家进入有16个房间的密室,除了玩家开始所在的餐厅之外,每个房间有若干宝石和幽灵,玩家需要集齐所有水晶来打开驱除幽灵,但要小心,不要被幽灵抓到。
游戏开始自动计时,没有时间限制,每摆脱一个幽灵可以获得一分,16个房间中随机散布着10个不同的宝石,除了邪恶的钟表房间有5个幽灵和餐厅没有幽灵之外,其余的房间只有3个幽灵,注意,每个房间东西南北的四个缝隙可能会被柜子或者壁橱堵住。
二、游戏效果
2.1 游戏效果
三、项目配置过程
到 AssetStore 下载:
| --------------------------------------- | --------------------------------------- |
四、实现思路
4.1 房间的划分与实现
- 我们划分了 4X4 个房间,每个房间为正方形,边长为10,不同的房间可能会有一些装饰(也是游戏过程中的障碍物),玩家初始位于的房间是7号,也就是餐厅,各个房间的编号如下:
4.2 Animator的实现
位于:Animation/Animator 中,受限于素材动画有限,Animator比较简单
4.2.1 PlayerAnimator
4.2.2 GhostAnimator
五、模块介绍 & 核心算法
5.1. Model模块
位于:MyScripts/Model,定义游戏对象的数据和工厂类。
5.1.1 Gem 宝石
GemData:宝石数据
public class GemData : MonoBehaviour{ public int gemID; // 宝石编号 public int gemRoomID; // 宝石所在房间 public bool isValid; // 是否还存在于地图中 public bool isCatch; // 玩家是否碰到宝石 }
GemFactory:工厂类,生成宝石
public class GemFactory : MonoBehaviour { private List<GemData> gems = new List<GemData>(); string gemsPath = "MyPrefabs/Gem/Gem"; string[] gemsID = new string[11] {"00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10"}; int[] gemX = new int[4] {-15, -5, 5, 15}; int[] gemZ = new int[4] {15, 5, -5, -15}; // 返回指定房间内的宝石 public GameObject GetGem(int roomID){ if(gems.Count != 0){ foreach(GemData existGem in gems){ if(existGem.gemRoomID == roomID){ return existGem.gameObject; } } } return null; } // 创建指定ID和房间的宝石 public GameObject GenGem(int gemID, int roomID){ GameObject gem = null; // 给出宝石的预制路径、根据房间ID算出位置和Quaternion string gemPath = gemsPath + gemsID[gemID]; int x = gemX[(roomID - 1) % 4]; int z = gemZ[(roomID - 1) / 4]; Vector3 pos = new Vector3(x, 1, z); Quaternion rot = new Quaternion(-0.707106829F, 0, 0, 0.707106829F); // 创建宝石对象 gem = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>(gemPath), pos, rot); // 创建碰撞检测器 gem.AddComponent<GemCollideSensor>(); // 为创建的宝石对象赋予数据 gem.AddComponent<GemData>(); if(gem != null){ GemData gemData = gem.GetComponent<GemData>(); gemData.gemID = gemID; gemData.gemRoomID = roomID; gemData.isValid = true; gemData.isCatch = false; gems.Add(gemData); } gem.SetActive(true); return gem; } // 删除宝石 public void FreeGem(GameObject gem){ foreach(GemData gemData in gems){ if(gemData.gameObject.GetInstanceID() == gem.GetInstanceID()){ gem.SetActive(false); gems.Remove(gemData); break; } } } }
宝石预制:
5.5 GUI模块
位于:MyScripts/View,简单界面交互。
5.5.1 UserGUI 界面交互
- 主要组件:
- 右上角刷新按钮:随时重新开始局一新的游戏,
- 正上方文本框:显示分数和计时。
六、实现过程中问题
6.1 SceneManager与光线渲染
问题发生在我们调用 SceneManager.LoadScene 获得新场景后,场景的亮度会变暗。
对此,我怀疑是Unity3D自动渲染的问题,一种可行的解决步骤如下:
首先,按照如下步骤进入 Lighting:菜单栏 - Window - Rendering - Lighting
然后,创建一个新的 Lighting Setting,创建后会进行编译,编译结束后,会在当前文件夹生成该配置,问题解决。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RiP8Z7PI-1662708482474)(image/8.png)]
本文含有隐藏内容,请 开通VIP 后查看