[读书笔记]<游戏引擎架构>|管理器的启动与终止

来源:互联网 发布:大学社团网络部职能 编辑:程序博客网 时间:2024/06/16 14:43

每个游戏都会包含一些底层支持系统, 例如资源管理器、日志系统、对象池、动画管理器、音乐/音效管理器等。这些管理器通常是一个单例类,如下面这段代码:

class ResourceManager{private:    static ResourceManager* m_pInstance;public:    static ResourceManager* get()    {        if(m_pInstance == nullptr)        {            m_pInstance = new ResourceManager();        }        return m_pInstance;    }};

我所在的项目之前就是使用这种方式实现的。
然而,这种方式有个极大的弊端,就是不能控制其构造和析构的时间。假如A管理器依赖B管理器,而在B管理器创建之前A已经被调用,或者B管理器已经被析构,而A还存在, 很有可能导致严重问题。
事实上这个实现方式确实导致过我们游戏崩溃。
于是上述设计被改成如下方案:

class ResourceManager{private:    static ResourceManager* m_pInstance;public:    static ResourceManager* get()    {        return m_pInstance;    }    static void createInstance()    {        m_pInstance = new ResourceManager();    }    static void destoryInstance()    {        delete m_pInstance;    }};//其他管理器...//class GOW{    static void Init()    {        ResourceManager::createInstance();        //其他管理器同上        ...        //    }    static void UnInit()    {        ResourceManager::destoryInstance();        //其他管理器同上        ...        //    }};

即明确的为各单例管理器定义构造和析构的函数,替代简单的get,这样就可以按所需的明确次序调用各启动和终止函数。
书中提到了更优雅的方法是:启动时将这些管理器按所需次序启动并放入一个栈中,这样终止时,可以逐一把管理器弹出栈并调用终止函数。根据这个思路,我想到如下实现:

class IManager{    static void startUp() = 0;//启动管理器    static void shutDown() = 0;//终止管理器};class ResourceManager: public IMananger{private:    static ResourceManager* m_pInstance;    ResourceManager()    {        //不做任何事    }    ~ResourceManager()    {        //不做任何事    }public:    static ResourceManager* get()    {        if(m_pInstance == nullptr)        {            m_pInstance = new ResourceManager();        }        return m_pInstance;    }    static void startUp() override    {        //管理器的启动代码    }    static void shutDown() override    {        //管理器的终止代码    }};//其他管理器...//class GOW{private:    static std::stack<IManager*> m_stkManager;    //这里使用栈的原因是,一般先启动的管理器更为基础,所以要后终止    static void InitManager(IManager* pMananger)    {        pManager->startUp();        m_stkManager.push(pMananger);    }public:    static void Init()    {        InitManager(ResourceManager::get());        //其他管理器同上        ...        //    }    static void UnInit()    {        while(!m_stkManager.empty())        {            auto* pManager = m_stkManager.top();            m_stkManager.pop();            pManager->shutDown();            delete pManager;        }    }};

这种方式有个好处,在新增或者修改导致一些管理器的依赖顺序改变时,只需要修改Init函数中的启动顺序,则终止的顺序也会跟着改变。引擎开发者只需要关注管理器的启动顺序就好。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 手机开直播很卡怎么办 小孩小鸡被虫子咬了怎么办 小鸡仔不吃食了怎么办 小鸡的腿瘸了怎么办 在境外住酒店钱被偷了怎么办 一加6屏幕辣眼睛怎么办 棉质衣服皱了怎么办 洗完衣服皱了怎么办 穿衬衫袖子很皱怎么办 洗完衣服有褶皱怎么办 麻料裤子容易皱怎么办 苹果手机邮件删了怎么办 飞猪12306登录不上怎么办 邮箱被别人绑定12306怎么办 白名单一个地址也没怎么办 12306忘记用户名和密码怎么办 12306忘了用户名和密码怎么办 12306注册后忘了密码怎么办 12306帐号忘了密码怎么办 12306忘了密码和手机号怎么办 12306账号密码邮箱忘了怎么办 注册12306账号没有邮箱怎么办 12306忘了用户名和邮箱怎么办 12306忘记用户名和邮箱怎么办 12306证件号码已被注册怎么办 12306忘记手机号和邮箱怎么办 发邮件被对方服务器退回怎么办 铁路12306显示已注册怎么办 qq密码太长输不进去怎么办 淘宝买家收货地址填写不全怎么办 护士电子注册账户未激活怎么办 您的邮件被退回怎么办 给国外发信被退怎么办 苹果8icloud满了怎么办 吃人参回奶了怎么办 邮箱被黑客黑了怎么办 传图识字有表格怎么办 手机qq收件箱图片打不开怎么办 腾讯企业邮箱一直被攻击怎么办 qq邮箱发送文件太大怎么办 苹果手机邮箱被删除了怎么办