一种Unity3D运行时资源管理方法和装置
技术领域
本发明涉及游戏开发技术领域,尤其涉及一种Unity3D运行时资源管理方法和装置。
背景技术
在网络游戏开发中,AssetBundle是Unity pro提供的一种用来存储资源的文件格式,它可以存储任意一种Unity引擎能够识别的资源,如Scene、Mesh、Material、Texture、Audio、noxss等等,同时,AssetBundle也可以包含开发者自定义的二进制文件,只需要将自定义文件的扩展名改为.bytes,Unity就可以把它识别为TextAsset,进而就可以被打包到AssetBundle中。Unity引擎所能识别的资源我们称为Asset,AssetBundle就是Asset的一个集合。现有的游戏客户端通常包括游戏运行时所需的所有游戏资源,例如,图片、音频和视频等资源。这些资源通常采用打AssetBundle包方式存储,从而获得传输方便、资源保密、以及更加快速访问速度等优点。
游戏中的所有对象本质上都是游戏对象(GameObject),游戏对象(GameObject)自身不会向游戏添加任何特性,而是容纳实现实际功能的组件(Component)的容器。例如,光(Light)是一个附加到游戏对象(GameObject)的组件(Component),Component(组件)是用来添加到GameObject对象上的一组相关属性,本质上每个组件都是一个类的实例,比如在Cube上添加一个Mesh网格,即面向对象的思维方式可以理解成Cube对象里包含了一个Mesh对象。Component主要包含以下组件:Mesh:添加网格类型的组件、Effects:添加特效类型组件、Physics:添加物理类型组件、Navigation:添加导航类型组件(比如自动寻路)等等。
Unity3D引擎提供的资源管理组件(AssetBundle)仅提供了最基础的资源生命周期控制接口,实际项目开发一般需要高度封装,使用过程中诸多不便,对开发人员的工程管理能力有较高要求。常见资源管理方法为对资源增加引用计数方式,每一个运行时对象对资源增加引用关系,则计数加1,解除引用则减1,计数为0则释放。引用计数方法需要精确成对操作,操作不匹配可能出现内存泄露或者资源丢失。引用计数无法处理循环引用情况。因此,需要提供一种基于Unity3D引擎提供的AssetBundle对象管理机制,实现资源的自动回收。
发明内容
本发明的目的是解决现有技术的不足,提供一种Unity3D运行时资源管理方法和装置,能够获得对资源自动回收,无需人工释放的效果。
为了实现上述目的,本发明采用以下的技术方案:
首先,在本发明的一个方法实施例中,提出一种Unity3D运行时资源管理方法,包括以下步骤:
S100,以有向图的方式对Unity3D运行时资源的依赖、引用状况进行建模;
S200,查找无父节点的GameObject对象;
S300,将所有AssetBundle节点设置为不可达状态;
S400,从无父节点的GameObject出发,递归遍历所有图节点,将途经的AssetBundle节点设置为可达状态;
S500,释放被标记为不可达状态的AssetBundle的资源。
在本发明的一个方法实施例中,以有向图的方式对Unity3D运行时资源的依赖、引用状况进行建模还包括以下步骤,建立Asset-AssetBundle映射表,记录Asset资源与AssetBundle之间的引用关系;对于取得实例化源对象对应的AssetBundle对象与引用该实例化源对象的GameObject对象,在映射表中记录其引用关系,如果被销毁的对象是一个GameObject,且有与之绑定的AssetBundle对象时,则解除引用关系。
在本发明的一个方法实施例中,通过设置一个定时器,在间隔一段时间进行资源回收处理。
在本发明的一个方法实施例中,递归遍历所有图节点是采用基于深度优先的遍历算法,在遍历过程中对遇到的GameObject和Asset对象进行查询是否跟AssetBundle对象绑定,如果跟AssetBundle对象绑定则将其绑定的AssetBundle对象标记为可达。
进一步地,遍历的图节点包括GameObject所有子对象和Component组件,针对常用Component组件定义引用收集器,为Component对象定义其在资源回收阶段的引用收集行为,在资源回收进程中对定义了引用收集行为的Component组件进行引用收集。
其次,在本发明的又一个方法实施例中,提出一种Unity3D运行时资源管理装置,包括以下模块:构建模块,用于以有向图的方式对Unity3D运行时资源的依赖、引用状况进行建模;查找模块,用于查找无父节点的GameObject对象;记录模块,用于记录AssetBundle节点的标记状态;修改模块,用于从无父节点的GameObject对象出发,递归遍历所有图节点,将途经的AssetBundle节点设置为可达状态;释放模块,释放被标记为不可达状态的AssetBundle的资源。
进一步地,在本发明的上述装置实施例中,修改模块对所有图节点进行递归遍历时采用基于深度优先的遍历算法。
再进一步地,在本发明的上述装置实施例中,Unity3D运行时资源管理装置还包括定时模块,与上述各模块连接,用于定时执行资源回收。
最后,在本发明的又一个方法实施例中,还提供了一种计算机可读存储介质,其上存储有计算机程序,该程序被处理器执行时实现本发明所述方法的步骤。
本发明的有益效果为:基于Unity3D引擎提供的AssetBundle对象管理机制,实现一种运行时资源自动回收方法。达到开发过程中,开发人员只需关注资源分配,无需人工释放的目的。
附图说明
图1所示为本发明的一个或多个实施例所公开的Unity3D运行时资源管理方法的方法流程图;
图2所示为本发明的一个或多个实施例所公开的资源管理方法中各类型对象的引用关系;
图3所示为本发明的一个或多个实施例所公开的资源管理方法中遍历各节点的示意图;
图4所示为本发明的一个或多个实施例所公开的Unity3D运行时资源管理装置的装置模块图。
具体实施方式
以下将结合实施例和附图对本发明的构思、具体结构及产生的技术效果进行清楚、完整的描述,以充分地理解本发明的目的、方案和效果。需要说明的是,在不冲突的情况下,本申请中的实施例及实施例中的特征可以相互组合。附图中各处使用的相同的附图标记指示相同或相似的部分。
本领域技术人员应当理解,在本申请的说明书中,“首先”、“其次”、“第一”、“第二”、“第一步”、“第二步”、“S200”等用语,如无特别声明并不表示对先后顺序的限制。例如,“步骤三”可以在“步骤一”之前,步骤“S300”可以和步骤“S200”同时进行。
参照图1所示的方法流程图,根据本发明所公开的第一实施例,提供了一种Unity3D运行时资源管理方法,包括以下步骤:
S100,以有向图的方式对Unity3D运行时资源的依赖、引用状况进行建模;
S200,查找无父节点的GameObject对象,将其视为根集;
S300,将所有AssetBundle节点设置为不可达状态;
S400,从根集出发,递归遍历所有图节点,将途经的AssetBundle节点设置为可达状态;
S500,释放被标记为不可达状态的AssetBundle的资源。其中,递归遍历所有图节点是通过采用。
在本发明的一个或多个实施例中,步骤S100使用有向图的方式对Unity3D运行时资源的依赖、引用状况进行抽象,图节点共有4种类型,分别是:AssetBundle、GameObject、Component、Asset。如果图2所示,各类型的对象之间的引用关系为:当一个AssetBundle有前置资源依赖时AssetBundle和AssetBundle之间存在引用关系;当一个GameObject是由AssetBundle中包含的Prefab对象实例化而成时,GameObject和AssetBundle之间存在引用关系;Asset是AssetBundle中所蕴含的资源时,Asset和AssetBundle之间存在引用关系;为GameObject对象添加组件时,GameObject和Component之间存在引用关系;GameObject之间存在父子关系时,GameObject和GameObject之间存在引用关系;某类型组件(例如RawImage可以引用Texture)拥有引用资源的能力且引用了Asset,则Component和Asset之间存在引用关系。通过有向图建模的方法可以把各类型对象之间的复杂引用关系清晰的表达出来,提高了释放资源的效率。同时在使用Unity3D进行开发的过程中无需关注运行时资源的释放难题,提高软件开发效率。
在本发明的一个或多个实施例中,在对各类型的对象引用状况进行建模时,还包括以下步骤:在AssetBundle对象中,使用LoadAsset接口取得Asset资源对象时,建立用于记录Asset资源与AssetBundle之间的引用关系的映射表;全局接管GameObject.Instantiate接口(用于创建GameObject的实例),对于取得实例化源对象对应的AssetBundle对象与引用该实例化源对象的GameObject对象,建立映射表,在映射表中记录AssetBundle和GameObject之间的引用关系,同时,全局接管GameObject.Destroy接口(用于销毁GameObject的实例),如果被销毁的对象是一个GameObject,且有与之绑定的AssetBundle对象时,则解除引用关系。
在本发明的一个或多个实施例中,对于常用Component组件定义引用收集器,为Component对象定义其在垃圾回收扫描阶段的引用收集行为。例如,针对UnityEngine.UI.Image,引用收集器为其返回material和sprite.texture属性;针对UnityEngine.UI.RawImage,引用收集器为其返回texture属性;针对UnityEngine.Renderer,引用收集器为其返回sharedMaterial属性;针对UnityEngine.Transform,引用收集器为其返回gameObject属性。
在本发明的上述方法的一个具体实施例中,执行资源回收处理时设置一个定时器,间隔一段时间执行资源回收程序,如图3所示,程序执行时,首先使用UnityEngine.SceneManagement.GetAllScenes接口取得当前所有运行场景,使用有向图的方式建立用于描述各对象之间引用关系的模型,将资源集合中的AssetBundle的标记状态设置为不可达;对场景列表依次使用UnityEngine.SceneManagement.Scene.GetRootGameObjects接口取得场景所有顶级(无父对象)GameObject,将这些GameObject集合作为根集(图中的根集包括GameObject 1和GameObject 2)进行扫描,遍历每个GameObject的所有子对象和Component组件,对定义了引用收集行为的Component组件进行引用收集,查询遍历过程中遇到的GameObject和Asset对象是否跟AssetBundle对象绑定,如果跟AssetBundle对象绑定则将与其绑定的AssetBundle对象标记为可达,在该具体实施例中,图3中的AssetBundle 2和AssetBundle 3的标记状态被修改为可达;最后不可达的AssetBundle 1执行AssetBundle.Unload(true)释放其资源,在该具体实施例中,AssetBundle 1将被释放其资源。
参照图4所示的装置模块图,根据本发明所公开的第二个实施例,提供了一种Unity3D运行时资源管理装置,包括以下模块:构建模块,用于以有向图的方式对Unity3D运行时资源的依赖、引用状况进行建模;查找模块,用于查找无父节点的GameObject对象;记录模块,用于记录AssetBundle节点的标记状态;修改模块,用于从无父节点的GameObject对象出发,递归遍历所有图节点,将途经的AssetBundle节点设置为可达状态;释放模块,释放被标记为不可达状态的AssetBundle的资源;定时模块,用于定时执行资源回收程序。
在本发明的上述装置实施例中,构建模块在对各类型的对象引用状况进行建模时,在AssetBundle对象中,使用LoadAsset接口取得Asset资源对象时,建立用于记录Asset资源与AssetBundle之间的引用关系的映射表;全局接管GameObject.Instantiate接口(用于创建GameObject的实例),对于取得实例化源对象对应的AssetBundle对象与引用该实例化源对象的GameObject对象,建立映射表,在映射表中记录AssetBundle和GameObject之间的引用关系,同时,全局接管GameObject.Destroy接口(用于销毁GameObject的实例),如果被销毁的对象是一个GameObject,且有与之绑定的AssetBundle对象时,则解除引用关系。
修改模块采用基于深度优先的遍历算法对所有图节点进行递归遍历,遍历每个GameObject的所有子对象和Component组件,对定义了引用收集行为的Component组件进行引用收集,查询遍历过程中遇到的GameObject和Asset对象是否跟AssetBundle对象绑定,如果跟AssetBundle对象绑定则将与其绑定的AssetBundle对象标记为可达。
根据本发明的第三实施例,提供了一种计算机可读存储介质,其上存储有计算机程序,该程序被处理器执行时实现本发明第一实施例所述方法的步骤。
尽管本发明的描述已经相当详尽且特别对几个所述实施例进行了描述,但其并非旨在局限于任何这些细节或实施例或任何特殊实施例,而是应当将其视作是通过参考所附权利要求考虑到现有技术为这些权利要求提供广义的可能性解释,从而有效地涵盖本发明的预定范围。此外,上文以发明人可预见的实施例对本发明进行描述,其目的是为了提供有用的描述,而那些目前尚未预见的对本发明的非实质性改动仍可代表本发明的等效改动。