改进飞碟(Hit UFO)游戏
基本介绍
游戏内容要求
- 靶对象为 5 环,按环计分
- 箭对象,射中后要插在靶上
增强要求:射中后,箭对象产生颤抖效果,到下一次射击 或 1秒以后
- 游戏仅一轮,无限 trials;
增强要求:添加一个风向和强度标志,提高难度
实现
UML
这个设计和打靶游戏的是一致的,主要是具体动作、控制器等具体实现有些是不同的。
靶
- 靶子是由5个圆柱体组成,每个圆柱体上添加一个Mesh Collider组件,勾选isTrigger做触发器使用。
- 每个圆柱体上挂载了CollisionDetection和RingData脚本。RingData脚本上只有一个分数属性,代表了这一环的分数。
最后预制体图如下:
弓和箭
使用的是资源LowpolyWeaponPack中的预制:
代码
部分代码都是沿用的打飞碟游戏的,就不一一展示了,就说明一下重点部分咯
- FirstSenceController
Update函数,使用LookAt函数将弓箭转向鼠标的方向,如果没有箭则从工厂中取出一支箭放在弓上,检测鼠标左键按下则射箭。
void Update () {
if(game_start) {
Vector3 mpos = Camera.main.ScreenPointToRay(Input.mousePosition).direction;
if (Input.GetButtonDown("Fire1")) {
Shoot(mpos * 15 );
}
if (arrow == null) {
arrow = arrow_factory.GetArrow();
arrow.transform.position = bow.transform.position;
arrow.gameObject.SetActive(true);
arrow.GetComponent<Rigidbody>().isKinematic = true;
}
bow.transform.LookAt(mpos * 30);
arrow.transform.LookAt(mpos * 30);
arrow_factory.FreeArrow();
}
}
Shoot函数:通知动作管理器根据初始的力和风力射箭,并且设置新的更强的风向。
public void Shoot(Vector3 force) {
if (arrow != null) {
arrow.GetComponent<Rigidbody>().isKinematic = false;
action_manager.ArrowFly(arrow, wind, force);
child_camera.GetComponent<ChildCamera>().StartShow();
arrow = null;
CreateWind();
round++;
}
}
- ArrowFlyAction
与打飞碟相同,实现箭飞行的动作,给一个冲击力和风力即可。
public class ArrowFlyAction : SSAction {
public Vector3 _force;
public Vector3 _wind;
private ArrowFlyAction() { }
public static ArrowFlyAction GetSSAction(Vector3 wind, Vector3 force) {
ArrowFlyAction action = CreateInstance<ArrowFlyAction>();
action._force = force;
action._wind = wind;
return action;
}
public override void Start() {
gameobject.GetComponent<Rigidbody>().AddForce(_force, ForceMode.Impulse);
gameobject.GetComponent<Rigidbody>().AddForce(_wind);
}
public override void Update() {}
public override void FixedUpdate(){
if (transform.position.y < -30) {
this.destroy = true;
this.callback.SSActionEvent(this);
}
}
}
- ArrowFlyActionManager
public class ArrowFlyActionManager : SSActionManager {
private ArrowFlyAction fly;
public FirstSceneController scene_controller;
protected void Start() {
scene_controller = (FirstSceneController)SSDirector.GetInstance().CurrentScenceController;
scene_controller.action_manager = this;
}
public void ArrowFly(GameObject arrow, Vector3 wind, Vector3 force) {
fly = ArrowFlyAction.GetSSAction(wind, force);
this.RunAction(arrow, fly, this);
}
}
- SSAction
动作基类 - SSActionManager
动作管理基类 - CollisionDetection
检测碰撞,将其挂在靶子的每一环上,使用OnTriggerEnter函数检测碰撞,碰撞之后将箭头隐藏并且将箭设置为运动学停止其运动。
public class CollisionDetection : MonoBehaviour {
public FirstSceneController scene_controller;
public ScoreRecorder recorder;
void Start() {
scene_controller = SSDirector.GetInstance().CurrentScenceController as FirstSceneController;
recorder = Singleton<ScoreRecorder>.Instance;
}
void OnTriggerEnter(Collider arrow_head) {
Transform arrow = arrow_head.gameObject.transform.parent;
if (arrow == null) return;
arrow.GetComponent<Rigidbody>().isKinematic = true;
arrow_head.gameObject.SetActive(false);
recorder.Record(this.gameObject);
}
}
- ChildCamera
在设定的时间内,显示副相机,可以让用户看清楚射出去箭在靶上的位置,挂载在副相机上。(初始设定副相机不显示)
public class ChildCamera : MonoBehaviour
{
public bool isShow = false; //是否显示副摄像机
public float leftTime; //显示时间
void Update()
{
if (isShow)
{
leftTime -= Time.deltaTime;
if (leftTime <= 0)
{
this.gameObject.SetActive(false);
isShow = false;
}
}
}
public void StartShow()
{
this.gameObject.SetActive(true);
isShow = true;
leftTime = 2f;
}
}
- interface
接口类 - ArrowFactory
工厂类 - RingData
射击环得分 - ScoreRecorder
记录得分 - UserGUI
用户界面设计 - Singleton
单实例 - SSDirector
游戏运行结果
后记
这个项目主要是碰撞问题,之前出现了箭一下子穿过去了的问题,然后看到了一个博客,记录一下。
当物体运动速度比较快或者碰撞体比较薄时,可能会出现穿过去而没有出发碰撞的情况,此时需要将速度快的物体即箭碰撞检测调为持续动态,将不动的物体碰撞检测设为持续。