关于引擎外存资源的管理问题

定义:外存资源指的是通过内容创建工具,比如 max\maya\photoshop\engine/game editor 等创建出来的存储在磁盘、光盘等外部设备的资源文件。

问题:通常外存资源之间存在引用关系,比如模型文件引用贴图、动画等,目前引擎的管理方式是直接在资源文件中包含被引用资源的相对路径文件名,但这两天对游戏资源目录的调整暴露了这个方法的严重问题:当资源目录改变时无法正确读取资源。实际上这种做法对于做数据库开发出身的我是非常不认可的,我们知道关系数据库在建立数据之间的关系时是通过对数据编号,然后指定关联的数据的编号即可,这是关系数据库的基础,通过编号来建立数据之间的关系。如果采用这种方式建立资源间的关系,用编号来标识资源,即使资源目录发生变化,甚至资源名称发生变化,也可以正常读取。在引擎开发的初始我也曾想这样做过,但如果真的这么做,却遇到了实际游戏开发中的问题。

    要做到对资源编号,就要求资源编号必定在统一的环境中生成,还是用关系数据库举例,数据库表中的数据的都是通过关系数据库系统的开发环境来创建的,创建的同时就指定了编号,所以可以做到通过编号引用数据。而游戏中的资源的创建却不是如此,如上面对外存资源的定义所说,资源是很多个不同的内容创建工具生成的,这种特殊的资源生成方式就决定了几乎无法做到统一的资源编号。当然,可以在每一个不同的工具中通过读取统一的资源编号列表文件来生成资源编号,但是资源往往是由多个人创建的,每个人都会修改这个统一的资源编号列表文件,这就会导致统一资源编号列表数据同步的问题,一旦产生同步错误,整个的游戏资源的管理就会陷入混乱。而且,在生成资源的同时,游戏开发团队中的其他人很可能会删除某些资源,为了保证资源编号的有效性,就必须要回收删除的资源编号,但这会更容易导致同步错误,所以这种方式不可取。那么主流的游戏引擎如何解决这个问题呢?

    Unreal:统一强大的游戏编辑器可以编辑游戏中所有资源,从这方面来说,它很容易做到资源统一编号,因为它有统一的数据生成环境。但是这种方式却不适合国内游戏的开发习惯,尤其不适合美术人员的使用习惯,通常 art 在 3dsmax \ photoshop 中做好 model \ texture 后通过导出插件导出到指定目录下就可以直接使用,但是 Unreal 却要求必须进行一次导入 Unreal 编辑器的操作,否则引擎无法直接使用导出资源。而实际的情况是 Art 希望导出资源后能立即看到渲染效果,然后对资源做相应的修改和调整。而 Unreal 本身的资源管理特性决定了无法做到这一点,要想看到最后效果,就必须导入 Editor。这种繁琐的操作对于 Art 来说是非常痛苦的。当然,如果经过一段时间的培训,不习惯也会习惯。

    Gamebryo \ Renderware:导出时可以即时看到资源的渲染效果,这对 Art来说很方便,而且可以将多个资源导出成一个包。但是和我们的引擎存在同样的问题:使用资源的文件路径\名称来定位引用的资源。Gamebryo \ Renderware内部的 API 提供了设置 Resource Path 的功能,甚至 Gamebryo在内部还做了局部的容错处理:当引用的资源无法加载时,尝试在当前资源所在的目录下加载引用资源。但即使这样,还是无法从根本上解决问题,在我看来,这种做法其实是纵容了资源管理的任意性,大大增加了资源目录结构混乱的可能性。

    从以上的分析似乎可以得出这样一个结论,要做到资源管理的灵活性,就要牺牲资源产生的便利性;要资源产生的便利性,就会失去资源管理的灵活性。也许这是无法调和的矛盾,或者,还有更好的解决办法?

Advertisements
此条目发表在DreamEngine 3D 图形引擎开发分类目录。将固定链接加入收藏夹。

9 Responses to 关于引擎外存资源的管理问题

  1. ixnehc说道:

    要不使用guid?

  2. 说道:

    GUID 的确能解决编码问题,但是维护 GUID 和资源的对应关系却是个麻烦的问题。总要有一个总体的资源维护来进行管理,否则只是给一个 GUID 是无法加载资源的。

  3. shi说道:

    老大,依我看怎样都该有个editor,即便是老版的gamebryo,也是有个什么都做不了只能看的map editor,之后的多语言版,加上ui,没有editor来打包资源游戏注定长不大的。
    到未见得非要用guid,相对路径的话算个hash弄进map就很快了吧。

  4. 说道:

    纠正一点,Gamebryo map 编辑器并不是处理资源之间的引用关系的.关于资源编辑器我也想做,但是有了它,所有的资源存储及引用关系都要经过它,举个例子,某天某程序突发奇想要把资源换个路径,如果不经过编辑器的话直接通过 windows 资源管理器移动资源,还是无法正确加载资源。为了保证引用正确性,还是要同过编辑器完成这个操作,但是这个过程太繁琐了。我们目前开发中就遇到了这个问题,资源路径存储结构经常变化,不是改个名字,就是换个路径,每次都要用编辑器来操作的话实在太不方便。
    我现在也没有完全解决这个问题,目前的解决方案是对于引用的资源使用相对于引用得资源的相对路径,然后通过一些特殊的处理,可以做到更改部分路径时依然可以做到正确加载资源,同时,我们还将提供资源编译器,在版本发布的最后时期可以将所有引用资源的关系列出来,通过编译器设置正确的路径引用关系。有了这两个措施,基本可以解决大部分的问题。

  5. 詹姆士说道:

    目前刚刚开始的项目我使用的办法是使用10位unsigned int值对资源进行统一编号
    例如:xx-xxx-xxx-xx   大类型(0~41)- 细分类型 – 小类型 – 附加编号
    每一段同时也是目录名,这样形成最终文件为10位(到顶了)
    美术制作之前对所有资源进行归类,这样只要给出一个unsigned int 类型的ID就可以定位到需要的资源了,目前没有发现不够用的现象

  6. 说道:

    这也是一种方法,实际上是将资源按照类别划分,但问题是有时项目中不一定会按照类别划分,比如按照关卡划分,甚至没有一定的分类原则,可能是任意存储,这种情况下这种方法就很难适应了.另外,资源的管理很难在项目初期就完全确定下来而不会更改,经常会爱开发过程中变换存储方式,这也是一个现实的问题.
    其实我的问题并不是生成如何生成编号,而是如何在资源存储位置发生改变时,依然能正确处理资源之间的引用关系,这是问题的关键.要做到这一点,只能有一个统一的资源生成入口 — 编辑器,所有美术生成的资源都要通过编辑器导入到引擎中,所有对资源位置的编辑也是通过编辑器来完成,这样的话资源的存储一定是 package 的形式,而不可能是分散独立的文件形式。

  7. 詹姆士说道:

    如果不使用编辑器等外部工具,那么最好的办法就是在命名规则上予以区分。
    美术提供的原始资源名称已经可以定位到所需要的资源,这样无论资源存储位置如何变化,都能正确定位到所需要的资源。之后可以根据需求定制打包工具等。而且就美术管理人员来说,这样的方式更便于美术的制作管理和开发进度安排,而且可以避免不同目录下资源重名的问题。
    编号的方式扩展性很强,即使资源类型前期不能全部想清楚但是后期应该只需要在之前的基础上进行扩展,同时这种方式也不受程序端存储方式改变的影响(因为是美术提供的原始资源)。
    美术的习惯其实很好培养,不用两个星期,他们看编号就像看到自己名字一样熟悉了,而且看到文件名就能知道是什么类型什么内容,甚至是谁制作的。
    你所说的需要编辑器生成的“统一资源生成入口”我的理解就是由美术来控制资源名称的不重复而且可定位(无需指定相对目录)。

  8. 说道:

    美术生成的资源都可以称之为 Raw 数据资源,这些资源不能被引擎直接使用,需要导入到引擎的资源编辑器中,经过处理(包括给资源编号、生成真实的资源数据、设定资源的存储位置等)之后才能被使用,这种资源生成的方式及流程我称之为统一的资源生成。有了这个处理,接下来的所有有关资源的操作,比如修改存储位置等,都在资源编辑器中完成,这样就保证了资源引用的正确性以及统一的资源编号。其实我说的这个过程是 UE3 的资源生成过程,目前引擎并没有采用这种方式,以后也许也会采用这个方式。如果这么做,Raw 资源的生成过程就是非常严格的资源制作过程,不能随随便便的导入到引擎中,那会造成资源的频繁的导入、修改,所以这需要一套严格的 Raw 资源生成流程来保证。

  9. ixnehc说道:

    可以这样,每个资源在创建的时候产生一个guid,别的资源引用它的时候,除了记录路径名以外再多记录一个guid,当读取资源时,首先根据路径名读取资源,如果找不到资源,或者找到资源,但是那个资源的guid不一样时,则认为这个引用路径已经失效了,这种情况下,由资源管理器负责修复路径名,根据guid在所有的资源中寻找这个资源,如果找到,则把找到的路径名更新原来的那个,如果找不到就报错.

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  更改 )

Google+ photo

You are commenting using your Google+ account. Log Out /  更改 )

Twitter picture

You are commenting using your Twitter account. Log Out /  更改 )

Facebook photo

You are commenting using your Facebook account. Log Out /  更改 )

w

Connecting to %s