您的位置:首页 > 运维架构 > 网站架构

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

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

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函数中的启动顺序,则终止的顺序也会跟着改变。引擎开发者只需要关注管理器的启动顺序就好。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐