2019-10-16

物理系统与碰撞

改进飞碟(Hit UFO)游戏

  • 游戏要求:
    • 按 adapter模式 设计图修改飞碟游戏
    • 使它同时支持物理运动与运动学(变换)运动

      adapter模式:

      适配器模式,即定义一个包装类,用于包装不兼容的接口对象

      包装类 = 适配器adapter
      被包装对象 = 适配者Adaptee = 被适配的类

类的适配器模式就是把适配的类的API转换成为目标类的API

从上图可以看出:
Target期待调用Request方法,而Adaptee并没有,为使Target能够使用Adaptee类里的SpecificRequest方法,提供一个Adapter类,继承Adaptee并实现Target接口。

  1. 创建Target接口
  2. 创建源类
  3. 创建适配器类Adapter
  4. 定义具体使用目标类,并通过Adapter类调用所需要的方法从而实现目标

    实现思路

    实现物理运动

    定义一个物理运动的类PhysicsAction

    实现飞碟的物理运动,添加Rigidbody组件,模拟物理运动
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    public class PhysicsAction : Action
    {

    private Vector3 startDirection; // 初速度方向
    private float power; // 控制飞碟速度的变量

    public static PhysicsAction GetAction(Vector3 direction, float angle, float power)
    {
    // 初始化飞碟的初速度方向
    PhysicsAction action = CreateInstance<PhysicsAction>();
    if (direction.x == -1)
    {
    action.startDirection = Quaternion.Euler(new Vector3(0, 0, -angle)) * Vector3.left * power;
    }
    else
    {
    action.startDirection = Quaternion.Euler(new Vector3(0, 0, angle)) * Vector3.right * power;
    }
    action.power = power;
    return action;
    }

定义物理运动的管理器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class PhysicsActionManager : ActionManager, ActionCallback
{

public PhysicsAction physics; // 物理动作

// 管理飞行
public void Fly(GameObject disk, float angle, float power)
{
physics = PhysicsAction.GetAction(disk.GetComponent<DiskData>().direction, angle, power);
this.RunAction(disk, physics, this);
}
public void ActionEvent(Action source, ActionEventType events = ActionEventType.Completed,
int intParam = 0, string strParam = null, object objectParam = null)
{ }
}

定义通用接口

适配器继承这个接口来进行运动的适配

1
2
3
4
public interface IActionManager
{
void Fly(GameObject disk, float angle, float power, bool physics);
}

实现适配器

适配器中包含两个运动管理器的实例,调用不同的运动管理器实现不同的运动模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class ActionManagerAdapter : MonoBehaviour, IActionManager
{

// 要适配的类
public FlyActionManager flyActionManager;
public PhysicsActionManager physicsActionManager;

public void Start()
{
flyActionManager = (FlyActionManager)gameObject.AddComponent<FlyActionManager>();
physicsActionManager = (PhysicsActionManager)gameObject.AddComponent<PhysicsActionManager>();
}

// 实现通用接口
public void Fly(GameObject disk, float angle, float power, bool physics)
{
if (physics)
{
physicsActionManager.Fly(disk, angle, power);
}
else
{
flyActionManager.Fly(disk, angle, power);
}
}
}

运动学运动实现方法

在Disk上添加Rigidbody组件,取消勾选重力

游戏视频

物理运动
运动学运动