欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unity实现鼠标打飞碟(Hit UFO)adapter模式

程序员文章站 2022-07-12 23:26:51
...

Unity实现鼠标打飞碟(Hit UFO)adapter模式

与上一版本的变化

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

适配器模式

适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式,它结合了两个独立接口的功能。
这种模式涉及到一个单一的类,该类负责加入独立的或不兼容的接口功能。举个真实的例子,读卡器是作为内存卡和笔记本之间的适配器。您将内存卡插入读卡器,再将读卡器插入笔记本,这样就可以通过笔记本来读取内存卡。

UML类图

由于采用了适配器模式,场景控制器可以通过一个适配器接口来选择不同的运动方式,可以很方便的从物理运动切换到运动学运动。增加了一个物理运动管理类。
Unity实现鼠标打飞碟(Hit UFO)adapter模式

代码分析
  • IActionManager
    场景控制器与适配器的接口,通过该接口场景控制器可以*选择不同的运动方式。
public interface IActionManager
{
    void playDisk(Disk disk, bool Mode);
}
  • PhysisFlyAction
    物理运动动作,控制飞碟的运动轨迹,为刚体飞碟设置重力和初速度,使得飞碟以不同的初速度和重力的影响下飞行。
public class PhysisFlyAction : SSAction
{
    public float Power = 10;//这个代表发射时的速度
    private Vector3 MoveSpeed = new Vector3(10,0,0);//初速度
    public DiskFactory diskfactory;
    public UserGUI User;
    public static PhysisFlyAction GetSSAction(float Power,float Angle,float Gravity,Vector3 MoveSpeed)
    {
        PhysisFlyAction action = ScriptableObject.CreateInstance<PhysisFlyAction>();
        action.Power = Power;
        action.MoveSpeed = MoveSpeed;
        return action;
    }
    public override void Update()
    {

    }

    public override void FixedUpdate(){
        if(this.transform.position.y < -7 || this.transform.position.x > 10){
            if(this.transform.position.x > 0 && User.HP > 0) User.HP--;
            diskfactory.FreeDisk(this.gameobject);
            this.destroy = true;
            this.callback.SSActionEvent(this);
        }
    }

    public override void Start(){
        //User = gameObject.AddComponent<UserGUI>() as UserGUI;
        gameobject.GetComponent<Rigidbody>().velocity =  MoveSpeed;
        gameobject.GetComponent<Rigidbody>().useGravity = true;
        diskfactory = Singleton<DiskFactory>.Instance;
        User = Singleton<UserGUI>.Instance;
    }
}

  • PhysisActionManager
    物理动作管理类,与CCActionManager一样,通过PhysisFlyAction来管理飞碟的飞行运动。
public class PhysisActionManager : SSActionManager
{
    private PhysisFlyAction diskfly;
    protected new void Start()
    {

    }

    public void fly_disk(Disk disk){
        diskfly = PhysisFlyAction.GetSSAction(disk.Power,disk.Angle,disk.Gravity,disk.MoveSpeed);
        this.RunAction(disk.getGameObject(), diskfly, this);
    }
}
  • Adapter
    适配器,该类继承了IActionManager接口,可以通过Mode状态的不同来选择不同的动作管理器,从而实现不同的运动方式。
public class Adapter : MonoBehaviour,IActionManager
{
    public MySceneActionManager actionManager;
    public PhysisActionManager actionManagerPhysis;
    public void playDisk(Disk disk, bool Mode){
        if(Mode){
            actionManagerPhysis.fly_disk(disk);
        }
        else{
            actionManager.fly_disk(disk);
        }
    }
    void Start (){
        actionManager = gameObject.AddComponent<MySceneActionManager>() as MySceneActionManager;
        actionManagerPhysis = gameObject.AddComponent<PhysisActionManager>() as PhysisActionManager;
    }
}
  • SSAction
    由于刚体运动比较适合使用FixedUpdate,因此增加几行代码
    public virtual void FixedUpdate()
    {
        throw new System.NotImplementedException();
    }
  • SSActionManager
    调用SSAction的FixedUpdate和Update,增加的代码如下
    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.FixedUpdate();
            }
        }

        foreach (int key in waitingDelete)
        {
            SSAction ac = actions[key];
            actions.Remove(key);
            DestroyObject(ac);
        }
        waitingDelete.Clear();
    }
  • Controll 动作管理类
    需要将原先的动作管理器改成Adapter,需要飞碟运动时,调用playDisk方法即可。
        //actionManager = gameObject.AddComponent<MySceneActionManager>() as MySceneActionManager;
        actionManager = gameObject.AddComponent<Adapter>() as Adapter;
  • UserGUI
    在用户界面提供了一个按钮,用户可以点击按钮来实现物理学和运动学运动的转换
        if(GUI.Button (new Rect (Screen.width-100, Screen.height-200, 100, 40), "ChangeMode")){
            Mode = !Mode;
        }

由于物理运动需要飞碟是刚体,所以为飞碟预制体增加一个刚体属性,并不勾选Use Gravity,这是防止运动学运动时飞碟受到一个初始重力。

运行截图

Unity实现鼠标打飞碟(Hit UFO)adapter模式

视频链接
代码链接

相关标签: 3D游戏