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
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是指定飞碟的序号,然后会给飞碟指定一连串随机的目的地
// 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);
}
如果飞碟被点击,会给飞碟指定向下掉的运动
//隐藏UFO
public void hideUFO(int num)
{
GameObject go = sceneController.goList[num];
go.transform.position = new Vector3(0, 0, -5);
}
隐藏UFO,当飞碟不用时,可以把它藏在摄像头的后面
检测点击函数 PickUpObject.cs 挂载在摄像头上
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中
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代表飞碟忙碌
这样就可以检测,飞碟是否在忙碌,如果不忙碌的话,就可以重生
// 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);
}
}
}

浙公网安备 33010602011771号