Unity3d实现鼠标打飞碟(Hit UFO)游戏
要求
1、编写一个简单的鼠标打飞碟(Hit UFO)游戏
- 游戏内容要求:
- 游戏有 n 个 round,每个 round 都包括10 次 trial;
- 每个 trial 的飞碟的色彩、大小、发射位置、速度、角度、同时出现的个数都可能不同。它们由该 round 的 ruler 控制;
- 每个 trial 的飞碟有随机性,总体难度随 round 上升;
- 鼠标点中得分,得分规则按色彩、大小、速度不同计算,规则可自由设定。
- 游戏的要求:
- 使用带缓存的工厂模式管理不同飞碟的生产与回收,该工厂必须是场景单实例的!具体实现见参考资源 Singleton 模板类
- 近可能使用前面 MVC 结构实现人机交互与游戏模型分离
如果你的使用工厂有疑问,参考:弹药和敌人:减少,重用和再利用;参考:Unity对象池(Object Pooling)理解与简单应用 代码质量较低,比较凌乱
具体代码请参考我的gitee
https://gitee.com/woodx9/unity-3D-homework/tree/master/HItUFO
运行效果图
完整图(上面没有把分数GUI录入)
因为熟练运用了上次牧师与魔鬼的框架,所以仅仅用一天时间就把打飞碟做出来了
设计:
1. 飞碟自身会旋转,加上附加的图片有漂亮的星星,所以有风火轮的既视感
2. 飞碟的总数量是20个,打死它们后,飞碟会重生
3. 当鼠标打掉飞碟后,飞碟会往下掉,而且玩家会获得加分,分数为飞碟到摄像头的距离
4. 飞碟的运行轨迹,它们的轨迹一定会经过,Z为50,25, 10,5的垂直与Z平面的随机点(这个随机点大概率在摄像头视野内)
5.随着分数的升高,飞碟的速度会越来越快
部署:
摄像头挂载
飞碟挂载
代码浅析:
飞碟运动 代码在CCActionManager.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | public void UFOToDestination( int num) { GameObject obj = sceneController.goList[num]; obj.transform.position = new Vector3(Random.Range(-1 * 100 / 2, 100 / 2), Random.Range(-1 * 100 / 2, 100 / 2), 100); CCSequenceAction css = CCSequenceAction.GetSSAction(1, 0, new List<SSAction> {shakeTheDestination(50), shakeTheDestination(25), shakeTheDestination(10), shakeTheDestination(5)}); //改变 goList_usedAndFree[i] = 1; sceneController.goList_usedAndFree[num] = 1; this .RunAction(obj, css, this ); } public CCMoveToAction shakeTheDestination( int positionZ) { return CCMoveToAction.GetSSAction( new Vector3(Random.Range(-1 * positionZ/2 , positionZ/2), Random.Range(-1* positionZ/2, positionZ/2), positionZ), SSDirector.getInstance().GetCreditCount() / 300 + 10); } |
输入num是指定飞碟的序号,然后会给飞碟指定一连串随机的目的地
1 2 3 4 5 6 7 | // UFO坠落 public void UFODrop( int num) { GameObject obj = sceneController.goList[num]; CCMoveToAction ccma = CCMoveToAction.GetSSAction( new Vector3(obj.transform.position.x, -100, obj.transform.position.z), 50); this .RunAction(obj, ccma, this ); } |
如果飞碟被点击,会给飞碟指定向下掉的运动
1 2 3 4 5 6 | //隐藏UFO public void hideUFO( int num) { GameObject go = sceneController.goList[num]; go.transform.position = new Vector3(0, 0, -5); } |
隐藏UFO,当飞碟不用时,可以把它藏在摄像头的后面
检测点击函数 PickUpObject.cs 挂载在摄像头上
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | using System.Collections; using System.Collections.Generic; using System.Diagnostics; using UnityEngine; public class PickupObject : MonoBehaviour { public GameObject cam; // Update is called once per frame void Update() { if (Input.GetButtonDown( "Fire1" )) { Vector3 mp = Input.mousePosition; //get Screen Position //create ray, origin is camera, and direction to mousepoint Camera ca; if (cam != null ) ca = cam.GetComponent<Camera>(); else ca = Camera.main; Ray ray = ca.ScreenPointToRay(Input.mousePosition); //Return the ray's hit RaycastHit hit; if (Physics.Raycast(ray, out hit)) { //如果游戏结束了就不能点击了 if (SSDirector.getInstance().gameEnd) return ; if (hit.collider.gameObject.tag.Contains( "Finish" )) { //plane tag } GameObject parentGameObject = hit.transform.parent.gameObject; SSDirector ssdDirector = SSDirector.getInstance(); // Debug.Log(parentGameObject.GetComponent<UFOController>().getNum()); 不能用这个确定UFO的index,原因未知 // 计算得分 按距离相机位置算分数 int credit = ( int )Vector3.Distance(parentGameObject.transform.position, new Vector3(0, 1, 0)); ssdDirector.AddCreditCount(credit); ssdDirector.ccam.UFODrop(ssdDirector.firstcontroller.getGameObjectIndex(parentGameObject.transform.position)); } } } } |
如果检测到点击,就计算得分,然后传给SSDirector函数
然后指定UFO执行坠落函数
那么如果UFO坠落之后,如何检测到它坠落了并且回收呢?
在SSActionManager.cs中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | foreach ( int key in waitingDelete) { SSAction ac = actions[key]; // 检查是不是掉落的UFO,如果是的话Y轴高度低于-90,然后检查actions中是否还有掉落UFO的运动,有的话就删除它们的运动,然后把它们移动到隐藏位置 // 如果不是掉落的UFO,则说明UFO已经到达指定位置,突围成功,游戏结束 if (ac.transform.position.y < -50) { foreach (KeyValuePair< int , SSAction> kv in actions) { SSAction t_ac = kv.Value; if (t_ac != ac && ac.gameobject == t_ac.gameobject) { t_ac.destory = true ; //隐藏 SSDirector ssdDirector = SSDirector.getInstance(); ssdDirector.ccam.hideUFO(ssdDirector.firstcontroller.getGameObjectIndex(ac.transform.position)); ssdDirector.firstcontroller.goList_usedAndFree[ssdDirector.firstcontroller.getGameObjectIndex(ac.transform.position)] = 0; } } } //到达了最终位置 else if (ac.transform.position.z <= 10) { //code SSDirector ssdDirector = SSDirector.getInstance(); ssdDirector.gameEnd = true ; } actions.Remove(key); Destroy(ac); } |
当检测到飞碟坠落后,它还有一个运动还在执行,即原先设置的运动轨迹,因此要找到并删除它。
如果有飞碟到了最终的位置,则通知SSDirector,结束游戏
在FirstController.cs中,有一个变量
public List<int> goList_usedAndFree; //0代表飞碟空闲,1代表飞碟忙碌
这样就可以检测,飞碟是否在忙碌,如果不忙碌的话,就可以重生
1 2 3 4 5 6 7 8 9 10 11 | // Update is called once per frame void Update() { for ( int i = 0; i < goList_usedAndFree.Count; ++i) { if (goList_usedAndFree[i] == 0) { SSDirector.getInstance().ccam.UFOToDestination(i); } } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」