改进鼠标打飞碟
1. 游戏要求
1.按照adapter模式设计图修改飞碟游戏。
2.使它同时支持物理运动与运动学运动。
adapter模式:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作。
其UML图如下所示:
就是改变原先的项目的接口,使得其能够支持物理运动和运动学运动。
2. 游戏实现
要使得飞碟支持物理运动和运动学运动就需要用到刚体Rightbody组件,这样我们就能够向对象施加力,以逼真的物理效果控制飞碟,同时也使飞碟有碰撞响应,更加逼真。
而且Rightbody不能够用Update函数进行更新,需要用到Fixedupdate函数更新,FixedUpdate 在每次进行物理更新前调用,因此在该函数中做出的任何更改都将直接处理。
3. 具体实现
下面只展示与上次作业相比不同的代码。
- 首先要将飞盘预制加上刚体(Rightbody)组件。
-
PhysicsDiskFlyAction
扫描二维码关注公众号,回复: 15868169 查看本文章规定了飞碟飞行的动作,当飞碟从左边飞入屏幕就给飞碟向左的力,当飞碟从右边飞入屏幕就给飞碟向右的力,当飞碟飞出屏幕外时,将飞碟速度置为0并摧毁该飞碟。与上次作业的主要区别是加入了刚体组件,并且用fixupdate函数更新飞碟的状态。
using System.Collections; using System.Collections.Generic; using UnityEngine; // 模拟飞行 public class PhysicsDiskFlyAction : SSAction { private Vector3 start_vector; public float power; private PhysicsDiskFlyAction() { } public static PhysicsDiskFlyAction GetSSAction(int lor, float power) { PhysicsDiskFlyAction action = CreateInstance<PhysicsDiskFlyAction>(); if (lor == -1) action.start_vector = Vector3.left * power; else action.start_vector = Vector3.right * power; action.power = power; return action; } public override void Update() { } public override void FixedUpdate() { if (transform.position.y <= -10f) { gameobject.GetComponent<Rigidbody>().velocity = new Vector3(0, 0, 0); this.destroy = true; this.callback.SSActionEvent(this); } } public override void Start() { gameobject.GetComponent<Rigidbody>().AddForce(start_vector*3, ForceMode.Impulse); } }
-
SSAction
加上FixedUpdate函数,使其适配物理引擎。
using System.Collections; using System.Collections.Generic; using UnityEngine; //动作基类 public class SSAction : ScriptableObject { public bool enable = true; public bool destroy = false; public GameObject gameobject; public Transform transform; public ISSActionCallback callback; protected SSAction() { } public virtual void Start() { throw new System.NotImplementedException(); } public virtual void Update() { throw new System.NotImplementedException(); } public virtual void FixedUpdate() { throw new System.NotImplementedException(); } }
4.SSActionManager
在update函数中加入FixedUpdate函数,使其适配物理引擎。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/*动作管理基类*/
public class SSActionManager : MonoBehaviour, ISSActionCallback {
private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();
private List<SSAction> waitingAdd = new List<SSAction>();
private List<int> waitingDelete = new List<int>();
protected void Update() {
foreach (SSAction ac in waitingAdd) {
actions[ac.GetInstanceID()] = ac;
}
waitingAdd.Clear();
foreach (KeyValuePair<int, SSAction> kv in actions) {
SSAction ac = kv.Value;
if (ac.destroy) {
waitingDelete.Add(ac.GetInstanceID());
}
else if (ac.enable) {
ac.Update();
ac.FixedUpdate();
}
}
foreach (int key in waitingDelete) {
SSAction ac = actions[key];
actions.Remove(key);
Object.Destroy(ac);
}
waitingDelete.Clear();
}
public void RunAction(GameObject gameobject, SSAction action, ISSActionCallback manager) {
action.gameobject = gameobject;
action.transform = gameobject.transform;
action.callback = manager;
waitingAdd.Add(action);
action.Start();
}
public void SSActionEvent(
SSAction source, SSActionEventType events = SSActionEventType.Competeted,
int intParam = 0, string strParam = null, Object objectParam = null) {
}
}
5.DiskFlyActionManager
管理飞碟动作,引入上面所写的PhisicsDiskFlyAction动作并重新写DiskFly函数。用于管理飞碟的动作。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DiskFlyActionManager : SSActionManager
{
public PhysicsDiskFlyAction ph_fly;
public FirstController scene_controller;
protected void Start()
{
scene_controller = (FirstController)SSDirector.GetInstance().CurrentScenceController;
scene_controller.myactionmanager = this;
}
public void DiskFly(GameObject disk, float power)
{
disk.GetComponent<Rigidbody>().isKinematic = false;
int loc = disk.transform.position.x < 0 ? 1 : -1;
ph_fly = PhysicsDiskFlyAction.GetSSAction(loc, power);
this.RunAction(disk, ph_fly, this);
}
}
代码及演示
代码位置 将hw6的assets拖到项目中,然后打开Resources中的myscene,运行即可。