改进飞碟(Hit UFO)游戏:
- 游戏内容要求:
- 按adpter模式设计图修改飞碟游戏
- 使它同时支持物理运动与运动学(变换)运动
Adapter模式
适配器模式(Adapter Pattern):将一个接口转换成客户希望的另一个接口,使接口不兼容的那些类可以一起工作,其别名为包装器(Wrapper)。
- 程序的UML图:
物理引擎
物理引擎(Physics Engine)是一个软件组件,它将游戏世界对象赋予现实世界物理属性(重量、形状等),并抽象为刚体(Rigid)模型(也包括滑轮、绳索等),使得游戏物体在力的作用下,仿真现实世界的运动及其之间的碰撞过程。
-
常用物理组件:
- Rigidbody 刚体组件
- 物体运动控制属性
- Collider 碰撞器
- 物体碰撞与碰撞检测属性
- Mesh 网格
- 物体形状属性
- Joint 连接器
-
Unity中物体发生碰撞的条件
Static Colider静态碰撞器 | Rigidbody Colider刚体碰撞器 | Kinematic Rigidbody Colider运动学碰撞器 | |
---|---|---|---|
Static Colider静态碰撞器 | Y | ||
Rigidbody Colider刚体碰撞器 | Y | Y | Y |
Kinematic Rigidbody Colider运动学碰撞器 | Y |
部分实现
PhysicsEmitAction :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PhysicsEmitAction : SSAction
{
public Vector3 speed;
public static PhysicsEmitAction GetSSAction()
{
PhysicsEmitAction action = CreateInstance<PhysicsEmitAction>();
return action;
}
public override void Start()
{
}
public override void Update()
{
if (transform.position.y < -10 || transform.position.x <= -20 || transform.position.x >= 20)
{
gameObject.GetComponent<Rigidbody>().isKinematic = true;
gameObject.GetComponent<Rigidbody>().velocity = Vector3.zero;
transform.position = Vector3.down;
callback.SSActionEvent(this);
}
}
}
PhysicsActionManager:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PhysicsActionManager : SSActionManager, ISSActionCallback, IActionManager
{
public FirstSceneController sceneController;
public List<PhysicsEmitAction> seq = new List<PhysicsEmitAction>();
public UserClickAction userClickAction;
public DiskFactory disks;
protected void Start()
{
sceneController = (FirstSceneController)SSDirector.getInstance().currentSceneController;
sceneController.actionManager = this;
disks = Singleton<DiskFactory>.Instance;
}
public void SSActionEvent(SSAction source, SSActionEventType events = SSActionEventType.Completed, int intParam = 0, string strParam = null, Object objParam = null)
{
disks.RecycleDisk(source.gameObject);
seq.Remove(source as PhysicsEmitAction);
source.destory = true;
if (FirstSceneController.times >= 30)
sceneController.flag = 1;
}
public void CheckEvent(SSAction source, SSActionEventType events = SSActionEventType.Completed, int intParam = 0, string strParam = null, Object objParam = null)
{
}
public void Pause()
{
if (sceneController.flag == 0)
{
foreach (var k in seq)
{
k.speed = k.transform.GetComponent<Rigidbody>().velocity;
k.transform.GetComponent<Rigidbody>().isKinematic = true;
}
sceneController.flag = 2;
}
else if (sceneController.flag == 2)
{
foreach (var k in seq)
{
k.transform.GetComponent<Rigidbody>().isKinematic = false;
k.transform.GetComponent<Rigidbody>().velocity = k.speed;
}
sceneController.flag = 0;
}
}
public void PlayDisk()
{
if (disks.used.Count > 0)
{
GameObject disk = disks.used[0];
float x = Random.Range(-5, 5);
disk.GetComponent<Rigidbody>().isKinematic = false;
disk.GetComponent<Rigidbody>().velocity = new Vector3(x, 8 * (Mathf.CeilToInt(FirstSceneController.times / 10) + 1), 6);
disk.GetComponent<Rigidbody>().AddForce(new Vector3(0, 8.8f, 0), ForceMode.Force);
PhysicsEmitAction physicsEmitAction = PhysicsEmitAction.GetSSAction();
seq.Add(physicsEmitAction);
this.RunAction(disk, physicsEmitAction, this);
disks.used.RemoveAt(0);
}
if (Input.GetMouseButtonDown(0) && sceneController.flag == 0)
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hitGameObject;
if (Physics.Raycast(ray, out hitGameObject))
{
GameObject gameObject = hitGameObject.collider.gameObject;
Debug.Log(gameObject.tag);
if (gameObject.tag == "disk")
{
gameObject.transform.position = new Vector3(100, 100, 100);
userClickAction = UserClickAction.GetSSAction();
this.RunAction(gameObject, userClickAction, this);
}
}
}
base.Update();
}
}