简易版GameFramework游戏框架搭建教程(二)Entry

我们从新建一个Unity项目开始,名字叫SimpleGameFramework(下文简称SGF)



建立好框架与其脚本的目录



然后就可以开始框架Entry部分的搭建了


在GF的设计中,框架被分为了两部分,一部分独立Unity引擎,另一部分则依赖于Unity引擎:


自然而然的,GF里Entry也被分为了两部分,既然我们要搭建的是简易版的GF,那在设计上就不采用一部分与Unity分离的形式,而是全部依赖于Unity


首先新建一个Base文件夹,用来存放构成框架基础的类文件,GF在总体设计上是Manager of Managers式的,我们就在Base下面新建一个名为ManagerBase的模块管理器基类

    /// <summary>
    /// 模块管理器基类
    /// </summary>
    public abstract class ManagerBase
    {
        /// <summary>
        /// 模块优先级,优先级高的模块会先被轮询,并且后关闭
        /// </summary>
        public virtual int Priority
        {
            get
            {
                return 0;
            }
        }

        /// <summary>
        /// 初始化模块
        /// </summary>
        public abstract void Init();

        /// <summary>
        /// 轮询模块
        /// </summary>
        /// <param name="elapseSeconds">逻辑流逝秒</param>
        /// <param name="realElapseSeconds">真实流逝秒</param>
        public abstract void Update(float elapseSeconds, float realElapseSeconds);

        /// <summary>
        /// 停止并清理模块
        /// </summary>
        public abstract void Shutdown();
    }

在SGF的设计中,各Manager并不继承 MonoBehaviour,那么里面的Update是在哪里被调用呢?答案是在Managers里,只有Managers需要去继承MonoBehaviour,因此在建立Managers之前,我们需要先建立一个用于MonoBehaviour的单例模板

    /// <summary>
    /// 脚本的单例模板基类
    /// </summary>
    public abstract class ScriptSingleton<T>  : MonoBehaviour where T : ScriptSingleton<T>
    {
        
        protected static T _instance;
        public static T Instance
        {
            get
            {
                if (_instance == null)
                {
                    //从场景中找T脚本的对象
                    _instance = FindObjectOfType<T>();

                    if (FindObjectsOfType<T>().Length > 1)
                    {
                        Debug.LogError("场景中的单例脚本数量 > 1:" + _instance.GetType().ToString());
                        return _instance;
                    }

                    //场景中找不到的情况
                    if (_instance == null)
                    {
                        string instanceName = typeof(T).Name;
                        GameObject instanceGO = GameObject.Find(instanceName);

                        if (instanceGO == null)
                        {
                            instanceGO = new GameObject(instanceName);
                            DontDestroyOnLoad(instanceGO);
                            _instance = instanceGO.AddComponent<T>();
                            DontDestroyOnLoad(_instance);
                        }
                        else
                        {
                            //场景中已存在同名游戏物体时就打印提示
                            Debug.LogError("场景中已存在单例脚本所挂载的游戏物体:" + instanceGO.name);
                        }
                    }
                }

                return _instance;
            }
        }

         void OnDestroy()
        {
            _instance = null;
        }

    }

然后就可以开始建立作为框架入口的Managers了

新建一个FrameworkEntry类,并继承我们刚才写的ScriptSingleton

/// <summary>
/// 框架入口,维护所有模块管理器
/// </summary>
public class FrameworkEntry : ScriptSingleton<FrameworkEntry>
{

}

在其中定义一个链表,用于维护所有的Manager

    /// <summary>
    /// 所有模块管理器的链表
    /// </summary>
    private LinkedList<ManagerBase> m_Managers = new LinkedList<ManagerBase>();

然后在Update方法里轮询所有Manager,调用它们的Update方法

void Update()
    {
        //轮询所有管理器
        foreach (ManagerBase manager in m_Managers)
        {
            manager.Update(Time.deltaTime, Time.unscaledDeltaTime);
        }
    }
以及在OnDestroy方法里清理所有Manager
 void OnDestroy()
    {
        //关闭并清理所有管理器
        for (LinkedListNode<ManagerBase> current = m_Managers.Last; current != null; current = current.Previous)
        {
            current.Value.Shutdown();
        }
        m_Managers.Clear();
    }

接着开始编写对外提供的,获取链表里指定类型的Manger对象的方法

    /// <summary>
    /// 获取指定管理器
    /// </summary>
    public T GetManager<T>() where T : ManagerBase
    {
        Type managerType = typeof(T);
        foreach (ManagerBase manager in m_Managers)
        {
            if (manager.GetType() == managerType)
            {
                return manager as T;
            }
        }

        //没找到就创建
        return CreateManager(managerType) as T;
    }

我们还需要一个供内部使用的创建Manager的方法

    /// <summary>
    /// 创建模块管理器
    /// </summary>
    private ManagerBase CreateManager(Type managerType)
    {

        ManagerBase manager = (ManagerBase)Activator.CreateInstance(managerType);

        if (manager == null)
        {
            Debug.LogError("模块管理器创建失败:" + manager.GetType().FullName);
        }


        //根据模块优先级决定它在链表里的位置
        LinkedListNode<ManagerBase> current = m_Managers.First;
        while (current != null)
        {

            if (manager.Priority > current.Value.Priority)
            {
                break;
            }

            current = current.Next;
        }
        if (current != null)
        {

            m_Managers.AddBefore(current, manager);
        }
        else
        {

            m_Managers.AddLast(manager);
        }

        //初始化模块管理器
        manager.Init();
        return manager;
    }
到这里,我们的Managers就完成了,是不是很简单呢?接下来,就可以开始着手对各个功能模块进行编写了
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值