1. texture = /foo/bar/miracle.png;

  方式 III - 基于 GUID 的引用

  (形如 {77BA2B2B-3EA5-4C49-A3D2-0DA6A03D2B44})

 

 

  1. texture = {77BA2B2B-3EA5-4C49-A3D2-0DA6A03D2B44};

 

  1. texture = v1_ui_mainframe_miracle_png_hd;

  呼~~终于说到这一次的实践了。

 

 

  1. texture = /foo/bar/miracle.png:bd37de66ffdcfd5bf544502a1fae1e99;
复制代码
  还好一句话就能说清楚:在路径后面加一个该资源的内容摘要 (算法随意不影响,目前使用 MD5) 就是我目前采取的方案。

  关键点那么与上面的方案相比,这个方案有何不同呢?

  1.资源重命名或移动时,能够做到自动检测和修改。

 

  • 一般情况下,如果仅仅是重命名或移动,根据内容算出来的摘要是不变的,当通过路径找不到资源时,通过比较摘要,就可以提示用户 (或自动重定向到) 重命名或移动后的资源。
    • 检测和修改是可惰性的,可延迟至对应的资源打开时再转换,不必立即一次性扫描和更新所有引用。
      • 重命名和更新可以在 OS 的文件系统内完成,无需在特定工具内。

        2.资源更新时自动识别和更新摘要。
       
      • 当资源发生变化时 (通常是美术/策划保存了一个新版本) 编辑器会在加载此资源的引用者时为其生成新的摘要。
        • 这个也是可惰性的,也就是加载了哪个资源,哪个资源才需要重新生成。

          3.不像 GUID 那样需要单独存储,无需额外的 metadata 文件管理负担。
         
        • 由于摘要没有产生资源以外的额外信息,随时可以根据资源本身生成,所以无需额外的 metadata 文件。

          4.简化全库范围的操作。
         
        • 方便检查重复资源 (全库比较摘要即可);
          • 全库范围自动修复所有的重命名和移动 (完全应用 1.);
            • 全库范围自动重算 (完全应用 2.)。

              实现逻辑

              有同学可能会问:“如果移动,重命名,更新等各种操作混杂在一起,我怎么知道什么时候该自动重定向,什么时候该更新摘要呢?”

              嗯,这就是路径 (Path) 和摘要结合 (Digest) 的精髓所在了。我们根据引用去查找资源时,是按照下面伪码的逻辑进行的:

             
            1. Resource* getResource(const std::string refString)
              • {
                • // 分解为路径和摘要两部分
                  • std::string path = GetPathPart(refString);
                    • std::string digest = GetDigestPart(refString);
                      •  
                      • // 尝试访问位于此路径的文件
                        • Resource* res = GetActualFile(path);
                          • if (res)
                            • {
                              • // 文件存在的情况,检查摘要是否一致
                                • if (digest == GetActualDigest(path))
                                  • {
                                    • return GetActualFile(path);
                                      • }
                                        • else
                                          • {
                                            • // 文件存在,摘要不一致,则认为是资源更新,重算摘要
                                              • RefreshDigest(path);
                                                • }
                                                  • }
                                                    • else
                                                      • {
                                                        • // 文件如果不存在,符合重命名/移动的条件,提示用户资源未找到,是否进行全库范围搜索
                                                          • if (/*在另一个地点找到了摘要符合的资源*/)
                                                            • {
                                                              • // 提示用户 (或自动) 更新引用路径
                                                                • RefreshPath(newPath);
                                                                  • }
                                                                    • else
                                                                      • {
                                                                        • // 提示资源缺失 (in-editor) 或使用 err-placeholder (in-runtime)
                                                                          • ...
                                                                            • }
                                                                              • }
                                                                                • }
            复制代码
              也就是说,路径的判定优先级高于摘要。在认定属于何种情况时,路径为主导,摘要为辅助。如果路径吻合但摘要不符,则认为属于资源更新的情况;如果路径失效,则使用摘要去全库匹配。两种行为分别针对两种不同情况的处理,泾渭分明,各司其职。

              批量处置

              上面的代码是单个资源获取的流程,实际上在编辑器中打开一张地图 (或一个 UI 界面) 时,如果一个资源一个资源地单独汇报和处置,效率就太低了,可以在全部加载完毕后,统一批量地进行一次全库范围的匹配,然后弹出一个汇报和处置的对话框。在这个处置对话框中,重命名/移动/更新都是叹号,而无法识别/找不到资源则是红色叹号,通常如果都是叹号的话直接全部更新就可以了。

              代码中的引用

              在代码中为了简便,可以仅使用路径即可。在运行游戏的过程中,会自动生成一个 digest_cache.txt 文件,每一行是一个资源的完整引用,可以把这个文件提交到版本管理的库中。这样,很容易通过程序手段在资源发生重命名,移动和更新等事件时,检测并更新这个文件,必要时,可提示用户代码内的路径需要更新。

              小结

              总得来说,这个方案具有以下的特征:

             
            • 良好的可读性;
              • 无需额外的 metadata 文件存储;
                • 对资源的重命名/移动无需在编辑器等专有工具内完成,没有潜在的破坏其他资源引用的心理负担;
                  • 唯一需要保证的是,重命名和移动资源的时候,不要同时更新其内容即可。

                    好了,关于这个资源引用管理的实践,到这里就讲完了。在资源管理方面,你有什么心得呢?欢迎跟我一起讨论。

                  相关阅读:一个有趣的交互BUG 兼谈游戏的引导系统
                  锐亚教育

                  锐亚教育,游戏开发论坛|游戏制作人|游戏策划|游戏开发|独立游戏|游戏产业|游戏研发|游戏运营| unity|unity3d|unity3d官网|unity3d 教程|金融帝国3|8k8k8k|mcafee8.5i|游戏蛮牛|蛮牛 unity|蛮牛