基于Unity3D实现的HitUFO鼠标打飞碟游戏
鼠标打飞碟游戏
作业要求
1、编写一个简单的鼠标打飞碟(Hit UFO)游戏
- 游戏内容要求:
- 游戏有 n 个 round,每个 round 都包括10 次 trial;
- 每个 trial 的飞碟的色彩、大小、发射位置、速度、角度、同时出现的个数都可能不同。它们由该 round 的 ruler 控制;
- 每个 trial 的飞碟有随机性,总体难度随 round 上升;
- 鼠标点中得分,得分规则按色彩、大小、速度不同计算,规则可自由设定。
- 游戏的要求:
- 使用带缓存的工厂模式管理不同飞碟的生产与回收,该工厂必须是场景单实例的!具体实现见参考资源 Singleton 模板类
- 近可能使用前面 MVC 结构实现人机交互与游戏模型分离
2、改进飞碟(Hit UFO)游戏:
- 游戏内容要求:
- 按 adapter模式 设计图修改飞碟游戏
- 使它同时支持物理运动与运动学(变换)运动
项目文档
游戏说明
这是一个用Unity3D实现的HitUFO游戏,玩家通过鼠标点击飞出的飞碟来获取分数。
游戏规则:
中间的红色飞碟回发射出若干小飞碟,玩家通过鼠标点击,击中飞碟则获得对应的分数。
一局游戏有5个回合,每个回合的难度不同,每个回合有10波,一波会发射出若干个飞碟,飞碟按照不同的方向和速度从红色的母飞碟中飞出。
一共有五种飞碟,它们通过颜色区分,不同的飞碟的分数、速度范围和方向范围都不一样
以下是回合的设置和飞碟的设置:
回合 1 2 3 4 5 Trial的数量 10 10 10 10 10 Trial的时间间隔(秒) 1.8 1.6 1.4 1.2 1.0 飞碟的等级范围 1-5 1-5 1-5 1-5 1-5 一个Trial的飞碟个数 5 7 10 14 19 - 在回合的设定中:一轮飞碟数目固定,但飞碟的等级是随机的,则将了游戏的不确定性。
飞碟等级 1 2 3 4 5 颜色 黄色 绿色 青色 蓝色 黑色 重量(千克) 0.6-1.4 1.2-2.8 1.4-4.6 1.6-6.4 1-9 分值 50 100 500 1000 5000 速度方向 -0.1~0.1 -2~2 -5~5 -10~10 -20~20 力的方向 -1~1 -2~2 -5~5 -10~10 -20~20 - 在飞碟的设定中:速度的方向的范围大小对应于发射范围的大小,越小范围越集中,越容易点击,力的方向和大小对发射后的轨迹有影响,值越大说明越难击中
计分遵循五轮叠加,显然黑色的飞碟更值得点击。
游戏效果
项目配置过程
- 新建一个3D项目
- 下载 Assets 文件夹,替换项目的空 Assets 文件夹
- 进入 Scenes 文件夹中双击 HitUFO 场景
实现思路 & 模块介绍
文件布局:
- /Assets
- /Resources
- /Icon // 游戏图标
- /Material // 颜色材料
- /Prefabs // 五种不同颜色的飞碟预制
- /SkyBox // 天空盒
- /Scenes // 游戏场景
- /Scripts
- /Controller
- /Action // 动作模块
- CCActionManager.cs // 平移运动管理器
- CCFlyAction.cs // 平移运动实现
- IActionManager.cs // 动作管理器接口
- ISSActionCallback.cs // 回调接口
- PhysisActionManager.cs // 物理运动管理器
- PhysisFlyAction.cs // 物理运动实现
- SSAction.cs // 抽象动作
- SSActionManager.cs // 动作管理器模板
- /Round // 回合模块
- RoundController.cs
- /Score // 计分模块
- ScoreRecorder.cs
- FirstController.cs
- ISceneController.cs
- Singleton.cs
- SSDirector.cs
- /Action // 动作模块
- /Model
- /Disk //飞碟模型
- DiskData.cs // 飞碟基本数据
- DiskFactory.cs // 工厂模式产生飞碟
- /Disk //飞碟模型
- /View //交互模型
- IUserAction.cs
- UserGUI.cs
- /Controller
- /Resources
- /Assets
在这个项目的组织上,和前两个作业基本一致,有很多代码都可以直接复用,如导演类、各种接口以及运动管理器模板等等。
UML类图:
以下是整个项目关键模块的说明:
单实例模板
通过设计这样的一个模板类,可以让所有继承了MonoBehaviour的类可以简单使用单例模式,在获取单例模式对象时,只需
Singleton<ClassName>.Instance
,例如获取单例飞碟工厂对象:diskFactory = Singleton<DiskFactory>.Instance;
单例模式的代码:
// @file: Assets/Controller/Singleton.cs public class Singleton<T> : MonoBehaviour where T : MonoBehaviour {protected static T instance;public static T Instance { get { if (instance == null) { instance = (T)FindObjectOfType (typeof(T)); if (instance == null) { Debug.LogError ("An instance of " + typeof(T) + " is needed in the scene, but there is none."); } } return instance; } } }
飞碟数据模板:一个飞碟有级别、质量、颜色、分数、速度和外力这些属性,我们提供使用ScriptableObject文件定制属性配置的功能,这样就能直接从 Asset 中将配置好的数据拖入。
// @file: Assets/Model/DiskData.cs [System.Serializable] public class DiskData : MonoBehaviour {[Tooltip("飞碟级别")]public int level;[Tooltip("飞碟质量")]public float mass;[Tooltip("飞碟颜色")]public Color color;[Tooltip("击中分数")]public int score;[Tooltip("初始速度")]public Vector3 speed;[Tooltip("恒定外力")]public Vector3 force; }[CreateAssetMenu(fileName = "DiskItem", menuName = "(ScriptableObject)DiskItem")] public class DiskItem : ScriptableObject {public string Name;[Tooltip("飞碟属性")]public DiskData diskData; }
道具工厂和对象池
在游戏中我们会频繁需要多个Disk对象,频繁地系统生成和销毁对象会对游戏造成不必要的负担,因此我们引入对象池。
顾名思义,对象池是一个存放了多个对象的池子,它维护两个队列,一个包含空闲的对象,另一个包含正在工作的对象。当我们需要生成一个游戏对象时,我们首先考虑空闲队列是否有空闲对象给我们直接使用,如果没有空闲对象在考虑系统生成新的游戏对象。
在程序运行的过程中我们动态维护对象池,一个对象完成其工作时将其加入到空闲对象池中,一个对象正在忙碌则将其放进忙碌队列中。
在代码中,我们通过维护两个DiskData的链表来维护创建的所有飞碟对象,通过
GetDisk
来从对象池中获取对象,通过FreeDisk()
来返还游戏对象。具体的代码分析我们在下一节中给出。
飞碟运动模块:通过
GetComponent()
为游戏对象添加这些属性:// @file: Assets/Controller/Action/PhysisFlyActon.cs // @line: 24-27 this.gameObject.GetComponent<Rigidbody>().isKinematic = false; this.gameObject.GetComponent<Rigidbody>().velocity = speed; this.gameObject.GetComponent<ConstantForce>().force = force; this.gameObject.GetComponent<ConstantForce>().torque = new Vector3(0.2F, 0, -0.2F);
飞碟默认受重力影响,我们设置了初速度的方向、力的方向和力矩的方向,前二者给游戏对象提供初速度和加速度,而力矩能够让飞碟产生一个轻轻摆动的效果,让飞碟飞出后能有姿态的变化。
而对于实现动作分离的其他部分,和上一次作业的内容基本一致,在此不再赘述。
回合控制器 RoundController 的设计:
五个属性分别表示
// @file: Assets/Controller/Round/RoundController.cs // @line: 12-17 float time; // 计时,当time满足一个trial的时间间隔时清零 int round; // 当前的回合数 int trial; // 当前轮数 int diskNum;// 当前回合一轮飞出的飞碟数目 bool start; // 回合开始的标记
Start()
函数:初始化,为属性赋值并获取单例对象SetMode(bool isPhysis)
函数:选择是否使用物理学运动模型,根据结果分选不同的运动管理器CCActionManager
orPhysisActionManager
// @file: Assets/Controller/Round/RoundController.cs // @line: 34-39 if(isPhysis){actionManager = Singleton<PhysisActionManager>.Instance as IActionManager; } else{actionManager = Singleton<CCActionManager>.Instance as IActionManager; }
GenerateDisk(int level)
:通过飞碟工厂产生飞碟对象,并为他赋予动作// @file: Assets/Controller/Round/RoundController.cs // @line: 43-46 GameObject disk = diskFactory.GetDisk(level); disk.transform.position = new Vector3(0, 0, 0); // 飞碟的发射点 disk.SetActive(true); actionManager.Fly(disk);
Update()
函数:时间敏感,相隔指定时间(Trial)发射一波飞碟,处理Round、Trial次数的切换if(start){time += Time.deltaTime;if(round > 5){ // 一共5轮start = false;return;}if(trial == 10){ // 每轮10波// NEXT ROUNDtrial = 0;round++;diskNum += round;}if(time >= 2.0F - round * 0.2F){ // 每波生成 diskNum 个飞碟// NEXT TRIALtime = 0.0F;for(int i = 0; i < diskNum; i++){GenerateDisk(Random.Range(1,6));} trial++;} }
核心算法
游戏对象的回收算法
因为在飞碟的设定中,不同的飞碟有着不同的颜色,对此我们创建了五个颜色不同的飞碟预制。
这使得,在创建一个飞碟时,它已经被制定了对应的预制(即飞碟颜色不能更改)
导致我们在对象池的会后利用时,一个蓝色飞碟只能使用对象池中空闲的蓝色飞碟,而不能使用其他颜色的飞碟。(也即只能重用同等级的飞碟)
因此有
GetDisk()
的代码如下:// @file: Assets/Model/Disk/DiskFactory.cs // @line: 22-47 GameObject disk = null;// 在空闲队列中寻找级别相同的对象,如果有则直接使用 bool find = false; for(int i = 0; i < freeDisks.Count; i++){if(freeDisks[i].level == level){disk = freeDisks[i].gameObject;freeDisks.RemoveAt(i);find = true;break;} }//如果找不到级别相同的飞碟对象,需要调用 Instantiate 新建一个 if(find == false){disk = GameObject.Instantiate<GameObject>(Resources.Load<GameObject>(Prefabs[level - 1]), Vector3.zero, Quaternion.identity);disk.AddComponent<DiskData>();disk.AddComponent<Rigidbody>();disk.AddComponent<ConstantForce>(); }//最后更新飞碟的速度、力的数据,让飞碟轨迹每次不同 if(disk != null){DiskData diskData = disk.GetComponent<DiskData>();setDiskData(diskData, level);busyDisks.Add(diskData); }return disk;
不同等级的飞碟生成算法:粗暴的数学拼凑来获得游戏说明那一节飞碟属性表的效果,通过Random每次生成不同的轨迹。
// @file: Assets/Model/Disk/DiskFactory.cs // @line: 62-98 if(level <= 1){diskData.level = 1;diskData.mass = 1.0F + Random.Range(-1F, 1F) * 0.4F;diskData.score = 50;diskData.speed = new Vector3(Random.Range(-0.1F, 0.1F), Random.Range(-0.1F, 0.1F), Random.Range(-0.1F, 0.1F));diskData.force = new Vector3(Random.Range(-1F, 1F), Random.Range(-1F, 1F), Random.Range(-1F, 1F)); } else if(level == 2){diskData.level = 2;diskData.mass = 2.0F + Random.Range(-1F, 1F) * 0.8F;diskData.score = 100;diskData.speed = new Vector3(Random.Range(-2F, 2F), Random.Range(-2F, 2F), Random.Range(-2F, 2F));diskData.force = new Vector3(Random.Range(-2F, 2F), Random.Range(-2F, 2F), Random.Range(-2F, 2F)); } else if(level == 3){diskData.level = 3;diskData.mass = 3.0F + Random.Range(-1F, 1F) * 1.6F;diskData.score = 500;diskData.speed = new Vector3(Random.Range(-5F, 5F), Random.Range(-5F, 5F), Random.Range(-5F, 5F));diskData.force = new Vector3(Random.Range(-5F, 5F), Random.Range(-5F, 5F), Random.Range(-5F, 5F));} else if(level == 4){diskData.level = 4;diskData.mass = 4.0F + Random.Range(-1F, 1F) * 2.4F;diskData.score = 1000;diskData.speed = new Vector3(Random.Range(-10F, 10F), Random.Range(-10F, 10F), Random.Range(-10F, 10F));diskData.force = new Vector3(Random.Range(-10F, 10F), Random.Range(-10F, 10F), Random.Range(-10F, 10F));} else if(level >= 5){diskData.level = 5;diskData.mass = 5.0F + Random.Range(-1F, 1F) * 4.0F;diskData.score = 5000;diskData.speed = new Vector3(Random.Range(-20F, 20F), Random.Range(-20F, 20F), Random.Range(-20F, 20F));diskData.force = new Vector3(Random.Range(-20F, 20F), Random.Range(-20F, 20F), Random.Range(-20F, 20F)); }
基于Unity3D实现的HitUFO鼠标打飞碟游戏相关推荐
- unity3d开发鼠标打飞碟游戏(Hit UFO)
这次我们用Unity3d开发一个简单的打飞碟游戏 游戏简介 游戏有3个回合,每个回合会发射n中颜色的飞碟,击中飞碟会得到相应的分数,其中,击中黄色飞碟得1分,击中蓝色飞碟得2分,红色飞碟4分,击不中不 ...
- 基于Unity3D开发的智能巡逻兵小游戏
智能巡逻兵小游戏 作业要求 游戏设计要求:智能巡逻兵 创建一个地图和若干巡逻兵(使用动画): 每个巡逻兵走一个3~5个边的凸多边型,位置数据是相对地址.即每次确定下一个目标位置,用自己当前位置为原点计 ...
- Unity3D游戏编程-鼠标打飞碟
Unity3D游戏编程-鼠标打飞碟 文章目录 Unity3D游戏编程-鼠标打飞碟 一.作业要求 二.项目配置 三.项目演示 视频演示 项目下载 文字说明 项目截图 四.前置内容 MVC模式 动作管理器 ...
- Unity3d Note5(鼠标打飞碟(Hit UFO)游戏)
1.作业要求 2.具体设计 (1).制备预制体作为飞碟 (2).了解一下Singleton模板类 (3).了解一下工厂模式 (3).设计具体要实现的类 3.程序代码 成果视频 1.作业要求 编写一个简 ...
- 【Unity3d学习】使用物理引擎——打飞碟游戏的物理引擎改进与射箭游戏设计
文章目录 写在前面 HitUFO的物理引擎改进版本 物理引擎的改进版本思路与实现 PhysicsAction PhysicsManager 新接口类IActionManager 动作管理器基类的变化 ...
- 基于Unity3d的虚拟装配中的机械运动仿真
基于Unity3d的虚拟装配中的机械运动仿真 前言 1.创建缸体相关的物体和对象 2.鼠标随意拖动和旋转物体的脚本 3.利用标记点进行虚拟装配 4.缸体的旋转 前言 在研究基于unity3d的虚拟装配 ...
- unity3d 模拟电脑实现_基于Unity3D三维电脑组装实验系统的实现
0 基于 Unity3D 三维电脑组装实验系统的实现 [摘要] 实验教学不仅能够培养学生的动手能力,而且还能起到巩固课本上理论知识 的作用.但是由于我们国家人口基数庞大,教育资源有限,实验器材紧缺, ...
- unity3d 模拟电脑实现_毕业论文 基于Unity3D的三维虚拟电脑组装实验系统开发
第 0 页 基于 Unity3D 三维电脑组装实验系统的实现 [摘要] 实验教学不仅能够培养学生的动手能力,而且还能起到巩固课本上理论知识 的作用.但是由于我们国家人口基数庞大,教育资源有限,实验器材 ...
- 基于Unity3D技术的纸牌消除游戏
基于Unity3D技术的纸牌消除游戏 1 项目的创建和资源的导入 在Project下创建好需要的四个文件夹,其中Resources文件夹是用来存放A-K和大小王正面纸牌资源,Textture文件夹用来 ...
- 基于Unity3D的AR小游戏开发【100011412】
本科毕业设计(论文) GRADUATION DESIGN(THESIS) 基于 Unity3D 的增强现实游戏程序 摘要 增强现实(AR)作为一项新兴技术近年来被越来越多的人群所获知,AR 也渐渐走进 ...
最新文章
- 4.9.3 方法注释
- tenserflow.js 环境搭建
- 2018“硅谷技划”随笔(一):再论中美员工福利巨大差距的背后
- 无锁HashMap的原理与实现
- 从零实现一个自定义 HTML5 播放器
- hadoop 提交程序并监控运行
- 单片机c语言应用100例第3版课后答案,单片机C语言应用100例(第3版)(含光盘1张)...
- python中的get函数_python之函数用法get()
- 10分钟带你了解python_ComeOn!10分钟带你了解Python的变量和数据类型
- Intel Sandy Bridge/Ivy Bridge架构/微架构/流水线 (12) - 执行核
- STM32 FSMC/FMC原理保姆级讲解(一)
- TKDE2022 | 最新深度学习推荐系统综述:从协同过滤到信息增强的推荐系统
- 如何用sklearn创建机器学习分类器?这里有一份上手指南
- html5表单新增验证属性,HTML5表单增强属性
- 软件基本功能测试用例,测试用例实例—常见功能测试点().docx
- 修改注册表解决每次打开office2010都会出现正在配置的问题
- Android学习笔记之MeasureSpec
- android控制动态按钮,Android编程动态按钮实现方法
- tp5框架中调用支付宝线上资金预授权alipay.fund.auth.order.app.freeze接口
- 我喜欢邓丽君,死掉了;