Unity3D 飞碟游戏改进版

飞碟游戏改进

这次作业在上一次打飞碟游戏的基础上增加了adapter设计模式,用来统一物理运动和运动学动作管理器的接口,使得游戏可以动态改变飞碟的行为,同时支持物理运动和运动学变换,具有更高的可扩展性。

适配器模式

adapter模式

在设计模式中,适配器模式(英语:adapter pattern)有时候也称包装样式或者包装(wrapper)。将一个类的接口转接成用户所期待的。一个适配使得因接口不兼容而不能在一起工作的类能在一起工作,做法是将类自己的接口包裹在一个已存在的类中。

在这个游戏中我采用对象适配器模式,adapter类持有不同的动作管理器对象,并实现想暴露的接口,这样做使用成本更低且更加灵活。具体结构可看UML图。

UML图

uml图

关键代码解释

动作管理器统一接口

首先定义我希望得到的动作接口

public interface IActionManager
    {
        void addForceOnUFO(GameObject UFO);
    }

适配器类

UFOActionAdapter 类实现了上面定义的接口并且分别持有PhysisActionManager 和CCActionManager 的单例对象。whichActionManager 用来表示当前使用的动作管理器是哪一个。

public class UFOActionAdapter : IActionManager
    {
        private PhysisActionManager physisActionManager;
        private CCActionManager ccActionManager;
        int whichActionManager = 0; // 0 -> CCActionManager, 1 -> PhysisActionManager

        public UFOActionAdapter()
        {
            physisActionManager = PhysisActionManager.getInstance();
            ccActionManager = CCActionManager.getInstance();
        }

        public void switchActionMode()
        {
            whichActionManager = 1 - whichActionManager;
        }

        public void addForceOnUFO(GameObject UFO)
        {
            if(whichActionManager == 1)
            {
                physisActionManager.addForce(UFO);
            }
            else
            {
                ccActionManager.addForce(UFO);
            }
        }
    }

物理运动管理器

PhysisActionManager主要给游戏对象刚体添加一个一定范围内随机生成的力,并且模式为Impulse模式,表示一个瞬时的力。

public class PhysisActionManager
    {
        private SceneController scene;
        private static PhysisActionManager instance;

        private PhysisActionManager()
        {
            scene = SceneController.getInstance();
        }

        public static PhysisActionManager getInstance()
        {
            if (instance == null) instance = new PhysisActionManager();
            return instance;
        }

        public void addForce(GameObject UFO)
        {
            Vector3 force = getRandomForce();
            UFO.GetComponent<Rigidbody>().useGravity = true;
            UFO.GetComponent<Rigidbody>().AddForce(force, ForceMode.Impulse);
        }

        private Vector3 getRandomForce()
        {
            int x = UnityEngine.Random.Range(-30, 31);
            int y = UnityEngine.Random.Range(30, 41);
            int z = UnityEngine.Random.Range(20, 31);
            float t = 0.7f + scene.getTrailNum() / 20;
            return new Vector3(x, y, z) * t;
        }
    }

运动学运动管理器

CCActionManager把游戏对象刚体属性useGravity设置为false,然后给予刚体一个速度使其朝着一个方向运动。

public class CCActionManager
    {
        private SceneController scene;
        private static CCActionManager instance;

        private CCActionManager()
        {
            scene = SceneController.getInstance();
        }

        public static CCActionManager getInstance()
        {
            if (instance == null) instance = new CCActionManager();
            return instance;
        }

        public void addForce(GameObject UFO)
        {
            // 控制飞碟向某个随机方向持续移动
            UFO.GetComponent<Rigidbody>().useGravity = false;
            UFO.GetComponent<Rigidbody>().velocity = new Vector3(5, 15, 5);

        }
    }

用户接口

UserInterface类的Update方法中检测鼠标右键,当被按下的时候切换动作管理器。

if (Input.GetButtonDown("Fire2"))
        {
            action.switchActionInNextRound();
        }

我们应该是等到下一个trial开始的时候才执行动作管理器的更改(如果需要更改的话),这里我在场记中用一个成员变量来标记是否需要更改,在控制发射飞碟之前再根据这个值来执行修改。代码如下:

public void switchActionInNextRound()
        {
            myStatusCtrl.showSwitchText();
            switchActionManager = true;
        }
public void launchUFO()
        {
            if (switchActionManager)
            {
                switchActionManager = false;
                myUFOCtrl.switchActionManager();
            }
            //每次发射之前清0分数
            myStatusCtrl.resetScore();
            myUFOCtrl.launchUFO();
        }

最终效果

这里写图片描述

视频演示地址如下:https://www.bilibili.com/video/av22511301/

所有代码见github:https://github.com/CarolSum/Unity3d-Learning/tree/master/hw5

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值