游戏引擎基于Handle的资源管理

基于Handle的资源管理方案,第一时间想到的应该是Windows了,但是真正想让我实施这个方案的,是《游戏编程精粹1》里面的游戏资源管理篇章的给出的方案。在《游戏编程精粹1》里面的资源标示Handle类,是一个极为简单的32位int类型,分为前16位的index和后16位的magic num,magic num主要是用来用作资源的校验的,在获取实例资源和删除实例资源的时候,都会校验一次。这两个数据合成一个int32用来标示唯一的资源。

union
    {
        enum
        {
            MAX_BITS_INDEX = 16,
            MAX_BITS_MAGIC = 16,

            MAX_INDEX = (1 << MAX_BITS_INDEX) - 1,
            MAX_MAGIC = (1 << MAX_BITS_MAGIC) - 1,
        };

        struct
        {
            unsigned mIndex : MAX_BITS_INDEX;
            unsigned mMagic : MAX_BITS_MAGIC;
        };

        uint mHandle;
    };

当然,这个Handle在书里面是定义成模板了,主要还是转为C++的习惯,变成一种强类型的标示吧,不同资源类型不能相互赋值和转化。

接来下是定义HandleManager,这个类也是一个模板,就跟名字一样,是用来管理Handle的,里面有两个vector,一个是保存正在使用的资源的vector,一个是删除资源后放入的free vector,当用户需要新建一个Handle的时候,会优先从free vector里面查找空的Handle,重新指向新的资源。

但是这个Handle的指向资源实例数组的index是不会变的,会变的只是magic num。总的来说,Handle还是变了。

template<typename DATA, typename RESHANDLE>
DATA * ResHandleMgr<DATA, RESHANDLE>::acquire(RESHANDLE &handle)
{
    uint index;
    if (mFreeSlots.empty())
    {
        index = mMagicNums.size();
        handle.init(index);
        DATA *pData = new DATA();
        mUserVec.push_back(pData);
        mMagicNums.push_back(handle.getMagic());
    }
    else
    {
        index = mFreeSlots.back();     // init后,magic num 会加一
        handle.init(index);
        mFreeSlots.pop_back();
        mMagicNums[index] = handle.getMagic();
    }

    //return (mUserVec.begin() + index);
    UserVec::iterator iter = mUserVec.begin() + index;
    return *iter;
}

这个大体就是《游戏编程精粹1》里面的引擎资源管理方案了,要保存资源很简单,持有Handle就行了,要获取和删除资源直接用Handle就行了。但是,估计大家也看来出什么问题了,资源没有自动释放的机制!!!!!!!

于是,我在Handle类里面加了个变量,用来作为引用计数,这里暂时没有引入智能指针(这个引用计数优化的方法应该可以加入一个内存池)

private:
    union
    {
        enum
        {
            MAX_BITS_INDEX = 16,
            MAX_BITS_MAGIC = 16,

            MAX_INDEX = (1 << MAX_BITS_INDEX) - 1,
            MAX_MAGIC = (1 << MAX_BITS_MAGIC) - 1,
        };

        struct
        {
            unsigned mIndex : MAX_BITS_INDEX;
            unsigned mMagic : MAX_BITS_MAGIC;
        };

        uint mHandle;
    };
        //保存引用计数
    uint *mpRefCount;

在Handle释放的时候,handle.release(),在Handle赋值的时候,handle.addRef,当(*mpRefCount) == 0的时候,就可以释放资源资源了。

一开始的时候,将引用计数设置为static std::map<int, int>(前面一个int表示Handle,后面一个表示引用次数),后来发现效率实在太低,于是改为 uint *mpRefCount指针这种形式,帧数上升了20 FPS左右。。。

这个Handle类大体长这个样子的,基本也可以实现资源的自动释放机制了

template<typename ResType>
class ENGINE_DLL ResHandle
{
public:
    ResHandle();
    ResHandle(const ResHandle &handle);

    ~ResHandle();

    void init(uint index);
    uint getIndex() const;
    uint getMagic() const;
    uint getHandle() const;

    bool isNull() const;

    operator uint() const;

    void addRef();

    void release();

    ResHandle &operator =(ResHandle handle)
    {
        mHandle = handle.getHandle();
        if (handle.isNull() == false)
        {
            assert(handle.mpRefCount != 0);
            if (isNull() == false && mpRefCount)
            {
                release();
                if (mpRefCount != 0)
                    assert(mpRefCount == handle.mpRefCount);
            }
        }
        mpRefCount = handle.mpRefCount;
        addRef();
        return *this;
    }

private:
    union
    {
        enum
        {
            MAX_BITS_INDEX = 16,
            MAX_BITS_MAGIC = 16,

            MAX_INDEX = (1 << MAX_BITS_INDEX) - 1,
            MAX_MAGIC = (1 << MAX_BITS_MAGIC) - 1,
        };

        struct
        {
            unsigned mIndex : MAX_BITS_INDEX;
            unsigned mMagic : MAX_BITS_MAGIC;
        };

        uint mHandle;
    };

    uint *mpRefCount;
};

template<typename ResType>
ResHandle<ResType>::ResHandle(const ResHandle &handle) :
mpRefCount(0)
{
    mHandle = handle.getHandle();
    mpRefCount = handle.mpRefCount;
    addRef();
}

template<typename ResType>
ResHandle<ResType>::~ResHandle()
{
    release();
}

template<typename ResType>
void ResHandle<ResType>::release()
{
    if (mHandle != 0)
    {
        --(*mpRefCount);
        if (*mpRefCount == 0)
        {
            //std::cout << "need delete !!!!" << std::endl;
            //delete operator
            //后面加入
            Log::getInstancePtr()->logMsg("release res handle = %d", mHandle);

            SAFE_DELETE(mpRefCount);
        }
    }
}

template<typename ResType>
void ResHandle<ResType>::addRef()
{
    if (mHandle != 0)
    {
        ++(*mpRefCount);
    }
}

template<typename ResType>
ResHandle<ResType>::ResHandle() :
mHandle(0),
mpRefCount(0)
{

}

template<typename ResType>
void ResHandle<ResType>::init(uint index)
{
    assert(isNull());
    assert(index <= MAX_INDEX);

    static uint sAutoMagic = 0;

    if (++sAutoMagic > MAX_MAGIC)
    {
        sAutoMagic = 1;
    }

    mIndex = index;
    mMagic = sAutoMagic;

    if (mpRefCount == 0)
    {
        mpRefCount = new uint;
    }
    *mpRefCount = 1;
}

template<typename ResType>
ResHandle<ResType>::operator uint() const
{
    return mHandle;
}

template<typename ResType>
bool ResHandle<ResType>::isNull() const
{
    return !mHandle;
}

template<typename ResType>
uint ResHandle<ResType>::getHandle() const
{
    return mHandle;
}

template<typename ResType>
uint ResHandle<ResType>::getMagic() const
{
    return mMagic;
}

template<typename ResType>
uint ResHandle<ResType>::getIndex() const
{
    return mIndex;
}

//-------------------------------------------------------------------

template < typename Tag>
inline bool operator != (ResHandle<Tag> l, ResHandle<Tag> r)
{
    return (l.getHandle() != r.getHandle());
}

template < typename Tag>
inline bool operator == (ResHandle<Tag> l, ResHandle<Tag> r)
{
    return (l.getHandle() == r.getHandle());
}
时间: 2024-09-30 09:25:43

游戏引擎基于Handle的资源管理的相关文章

转:高层游戏引擎——基于OGRE所实现的高层游戏引擎框架

高层游戏引擎——基于OGRE所实现的高层游戏引擎框架 这是意念自己的毕业论文,在一个具体的实践之中,意念主要负责的是物件和GUI之外的其他游戏系统.意念才学疏陋,望众位前辈不吝赐教.由于代码质量不高.环境很难于配置.资源包过大等问题,意念暂先不提供代码和程序,未来有时间的时候组织一下这些曾经的代码,再向外发布. 文过三月,也有些新的想法,以后会慢慢跟大家聊的,欢迎拍砖哦^_^. 关键字与术语: 游戏. 游戏引擎 .高层引擎.规则 .场景.物件.Terrain(地形).解释器 .Applicati

对HGE游戏引擎的一次封装

HGE游戏引擎是一个开源2D游戏引擎,基于directX. 它的渲染及逻辑是基于帧回调的框架模式, 其提供一些主要的图像操作和输入控制功能. 我在之前写一个2D游戏的时候对它整个框架进行了一次封装,非常多地方写得比較恶心,请原谅我在变量上命名的不规范. 在此分享出来,主要能够參考一下大体框架吧. HGE游戏引擎基于帧的回调让我非常不爽,由于咱的游戏逻辑通常是连续的,跟详细帧无关,所以我把整个HGE跑在自己的一个线程之中.我的游戏逻辑部分通过发消息,通知界面更新 以及获取用户输入. 在HGE的主框

【课程下载】基于Cocos2d-x游戏引擎实战开发炸弹超人

我这里有套课程想和大家分享,需要的朋友可以加我qq和我联系.QQ2059055336. 课程讲师:Jason.Z 课程分类:ios适合人群:初级课时数量:31课时更新程度:完毕 一.本课程是怎么样的一门课程(全面介绍) 1.1.课程的背景 Cocos2d-x 是一个支持多平台的 2D 手机游戏引擎,使用 C++ 开发,基于OpenGL ES,基于Cocos2d-iphone,支持 WOPhone, iOS 4.1, Android 2.1 及更高版本, WindowsXP & Windows7,

Atitit 基于dom的游戏引擎

1. 添加sprite控件(cocos,createjs,dom)1 1.1.1. Cocos1 1.1.2. createjs1 1.1.3. Dom模式2 1.2. 动画移动的实现原理2 1.3. 动画移动(cocos2d-js,jquery animate,create.js)2 1.4. ---code3 1. 添加sprite控件(cocos,createjs,dom) 1.1.1. Cocos // var sushi = new cc.Sprite(res.Sushi_png);

变态版大鱼吃小鱼-基于pixi.js 2D游戏引擎

之前用CSS3画了一条??,那还是一年前的事情了,这次我用一天的时间去研究了一下pixi.js,一个基于webgl的2D游戏引擎,然后用它做了一个demo出来,变态版大鱼吃小鱼. 试玩地址:变态版大鱼吃小鱼 这是一个h5游戏排名,我最看好pixi,刚开始也试过create.js,不过它不支持webgl,这是一个硬伤,然后又了解了一下Phaser,基于pixi开发的,功能肯定比pixi强大,不过我觉得它太重了,好像是500多K,不适合做小游戏,而pixi只有90K,并且支持webgl,所以就选它了

浅析游戏引擎的资源管理机制

欢迎来到unity学习.unity培训.unity企业培训教育专区,这里有很多U3D资源.U3D培训视频.U3D教程.U3D常见问题.U3D项目源码,[狗刨学习网]unity极致学院,致力于打造业内unity3d培训.学习第一品牌. 游戏中通常有大量资源,如网格.材质.纹理.动画.着色器程序和音乐等,游戏引擎作为做游戏的工具,自然要提供良好的资源管理,让游戏开发者用最简单的方式使用资源.游戏引擎的资源管理包括两大部分:离线资源管理和运行时资源管理.本文仅对前者进行简要介绍,并结合Unity3D和

推荐一款基于XNA的开源游戏引擎《Engine Nine》

一.前沿导读 XNA是微软基于.Net部署的下一代3D/2D游戏开发框架,其实XNA严格来说类似下一代的DirectX,当然不是说XNA会取代DirectX,但是基于XNA我们对于面向XBOX360,WP等系列其他平台的移植成本非常的低(据说基于MONO在linux下XNA也可以运行3D DEMO,有试过的请点意见). 但是基于XNA的复杂程度我们自然也是可想而知的,所以在这里推荐第一款基于XNA的游戏引擎,Engine Nine. 二.Engine Nine介绍 Engine Nine是一款基

浅析游戏引擎的资源管理机制——扒一扒Unity3D中隐藏在背后的资源管理

      游戏中通常有大量资源,如网格.材质.纹理.动画.着色器程序和音乐等,游戏引擎作为做游戏的工具,自然要提供良好的资源管理,让游戏开发者用最简单的方式使用资源.游戏引擎的资源管理包括两大部分:离线资源管理和运行时资源管理.本文仅对前者进行简要介绍,并结合Unity3D和OGRE进行分析. 资源创作与导出 游戏中的资源由各种数字内容创作工具(DCC, digital content creation)进行创作,如: 三维模型:3ds Max,Maya等: 纹理:Photoshop等: 音乐

基于Laya游戏引擎实现微信小游戏排行榜

我们都知道,微信小游戏和小程序目前风头十足,很多公司都逐渐增加了相关业务线来迅速推广自己的产品和抢占用户群.说到微信小游戏,就不得不提到排行榜这个功能,就目前游戏行业,似乎都离不开排行榜这个重要功能,用户很大一部分留存都是依仗这个看似不起眼的模块.那么,微信小游戏中具体该如何借助laya引擎实现排行榜这个功能呢?我们先来看一下最终的效果图: 按照微信官方的说法,如果我们要使用微信官方提供的好友关系链的数据,我们就不能直接在项目中绘制排行榜,我们需要借助于开放域来绘制排行榜: ? 如果想要展示通过