实践内容
改进飞碟(Hit UFO)游戏:
实践要求:
- 按 adapter模式设计图修改飞碟游戏
- 使它同时支持物理运动与运动学(变换)运动
分析
-
Adapter 模式设计
Adapter模式可以将一个类的接口转换成客户希望的一个接口,使得原本由于接口不兼容的类能一起工作。
在本次实践中,将原来方便场记调用动作的动作管理类改为了FirstActionManager改为适配器接口IActionManager,并用这个接口来兼容SSActionManager和PhysicActionManager动作管理类,从而同时支持运动学运动和物理运动。 -
动力学的相关知识(Dynamics)
1)考虑外部力对物体运动的影响 ,包括重力、阻力、摩擦力等,
2)考虑物体的重量和形状, 甚至弹性物体
3)通常模拟物体在现实世界中的运动
4)通常将一个物体当作刚体
在unity中主要是通过- 向物体添加刚体组件(包括质量 mass 、阻力 Drag 、角阻力 、重力 等属性)component →physics → rigidbody
- 添加力(包含力和力矩属性) component → physics → constant force
等方式实现
代码
- IActionManager
定义接口来兼容SSActionManager和PhysicActionManager动作管理类,从而同时支持运动学运动和物理运动
public interface IActionManager
{
void diskFly(GameObject disk, float angle, float power);
}
- 运动学运动SSActionManager
和上次作业相比,直接把FirstActionManager里面的飞碟飞行功能添加进来了,使它能直接匹配适配器的接口
public class SSActionManager : MonoBehaviour, ISSActionCallback, IActionManager //继承IActionManager
{
private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();
private List<SSAction> waitingAdd = new List<SSAction>();
private List<int> waitingDelete = new List<int>();
public DiskFlyAction fly; //添加部分
public FirstController scene_controller; //添加部分
protected void Start()
{
scene_controller = (FirstController)Director.GetInstance().currentSceneController;
scene_controller.actionManager = this;
}
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();
}
}
foreach (int key in waitingDelete)
{
SSAction ac = actions[key];
actions.Remove(key);
DestroyObject(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.Completed,
int intParam = 0, string strParam = null, Object objectParam = null)
{
}
public void diskFly(GameObject disk, float angle, float power)//添加部分
{
fly = DiskFlyAction.GetSSAction(angle, power);
this.RunAction(disk, fly, this);
}
}
- 物理学运动PhysicActionManager
在本次实验中,向飞碟添加Rigidbody实现运动,
每个飞碟会被赋予一个随机的初速度velocity,关闭使用重力,让飞碟运动的更自由,添加阻力drag,阻力根据出入的power来设置,drag越小,飞行速度越快。
public class PhysicActionManager : MonoBehaviour, IActionManager
{
private Dictionary<int, SSAction> actions = new Dictionary<int, SSAction>();
private List<SSAction> waitingAdd = new List<SSAction>();
private List<int> waitingDelete = new List<int>();
public DiskFlyAction fly;
public FirstController scene_controller;
protected void Start()
{
scene_controller = (FirstController)Director.GetInstance().currentSceneController;
scene_controller.actionManager = this;
}
protected void FixedUpdate()
{
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();
}
}
foreach (int key in waitingDelete)
{
SSAction ac = actions[key];
actions.Remove(key);
DestroyObject(ac);
}
waitingDelete.Clear();
}
public void diskFly(GameObject disk, float angle, float power)
{
disk.GetComponent<Rigidbody>().velocity = new Vector3(Random.Range(-10, 10), Random.Range(-10, 10), Random.Range(-10, 10));
disk.GetComponent<Rigidbody>().useGravity = false;
disk.GetComponent<Rigidbody>().drag = (30 - power) / 20;
}
public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Completed,
int intParam = 0, string strParam = null, Object objectParam = null)
{
}
}
- FirstController
将原来的FirstActionManager组件换为动作管理器Adapter接口,添加管理器时使用具体的SSActionManager或PhysicActionManager来实例化
public class FirstController : MonoBehaviour, ISceneController, UserAction
{
public int round;
public int trial;
public float interval;
public int score;
private UserGUI userGUI;
private Ruler ruler;
//public FirstActionManager actionManager; //删除部分
public IActionManager actionManager; //添加部分
public GameObject cam;
private Queue<GameObject> disksQueue = new Queue<GameObject>();
private bool isRestart;
void Awake()
{
Director director = Director.GetInstance();
director.currentSceneController = this;
director.currentSceneController.loadResources();
userGUI = gameObject.AddComponent<UserGUI>() as UserGUI;
//actionManager = gameObject.AddComponent<FirstActionManager>() as FirstActionManager; //删除部分
actionManager = gameObject.AddComponent<SSActionManager>() as IActionManager; //添加部分
//actionManager = gameObject.AddComponent<PhysicActionManager>() as IActionManager; //添加物理运动管理器
ruler = gameObject.AddComponent<Ruler>() as Ruler;
cam.transform.position = new Vector3(0,-2,-15);
}
//...
}
游戏效果:
运动控制的效果和上次一样,物理控制的效果会有些抛体运动的效果
物理运动版视频