Unity3d实现鼠标打飞碟(Hit UFO)游戏

要求

1、编写一个简单的鼠标打飞碟(Hit UFO)游戏

  • 游戏内容要求:
    1. 游戏有 n 个 round,每个 round 都包括10 次 trial;
    2. 每个 trial 的飞碟的色彩、大小、发射位置、速度、角度、同时出现的个数都可能不同。它们由该 round 的 ruler 控制;
    3. 每个 trial 的飞碟有随机性,总体难度随 round 上升;
    4. 鼠标点中得分,得分规则按色彩、大小、速度不同计算,规则可自由设定。
  • 游戏的要求:
    • 使用带缓存的工厂模式管理不同飞碟的生产与回收,该工厂必须是场景单实例的!具体实现见参考资源 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);
            }
        }
    }

 

 

posted @   woodx  阅读(347)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示