话说,经过这段时间的学习和摸索,对于Unity3D的开发思路已经基本清晰了。唯独还剩下一个AssetBundle机制还没有搞透,这个涉及到前期项目的资源规划、资源管理代码的写法,以及自动更新机制的实现。

所以,还是想先把游戏逻辑的进一步分析押后,先来看一下《炉石传说》Asset管理。必须得说一下的是,目前分析都是PC版的程序集,对于移动端不一定完全合适,且当做一个案例分析吧。

本文主要讲述《炉石传说》的AssetBundle的管理机制。它的机制比较简单清晰,中规中矩,中间的分析过程就不讲了,直接展现其架构设计和代码逻辑组织。先从Asset管理相关的类讲起。

class Asset:资源信息描述

Asset类,并不管理直接的资源对象,而是保存的一个Asset相关的信息,具体请看上图。

另外,它还有一个“paths”变量,这是一个Dictionary,key是AssetFamily枚举,value是Assetbundle的路径和资源路径。下面的AssetFamily一节详细解释。

enum AssetFamily-资源分类

如上图所示:

  • 炉石根据资源的不同类型进行分别的AssetBundle打包,一类资源对应一个或者多个资源包;(一类资源分多个包的规则不得而知);
  • 有的资源包真的本地化单独打包,例如“fonts0.unity3d”==》“fontszhCN0.unity3d”;
  • 在程序中,资源包的分类对应枚举类型“AssetFamily”;
  • 资源包的具体路径信息,存储在Asset.paths,这是一个静态变量;在初始化时,手动填写必要的信息,类似这样:
  1. Dictionary<AssetFamily, AssetFamilyPathInfo> dictionary = new Dictionary<AssetFamily, AssetFamilyPathInfo>();
  2. AssetFamilyPathInfo info = new AssetFamilyPathInfo {
  3. format = "Data/Actors/{0}.unity3d",
  4. sourceDir = "Assets/Game/Actors"
  5. };
  6. info.exts = new string[] { "prefab" };
  7. dictionary.Add(AssetFamily.Actor, info);

复制代码

  • 另外,还有一个class AssetBundleInfo是记录了每种AssetBundle对应的主文件名,以及包文件的个数、对应的对象类型等信息;详见下图:

class AssetLoader:资源加载

游戏运行时需要加载各种资源,基本上都是通过AssetLoader(也有个别情况适用了Resources.Load())。接下来我们就重点看一下AssetLoader的实现思路。

AssetLoader对上层提供资源对象加载接口,对于每种类型的资源都提供一组函数,例如LoadCardPrefab,LoadActor等等。对于对象加载完成、加载进度等提供回调函数。这些函数只是一些简单的包装,其内部都调用到LoadCachedGameObject()或LoadCachedObject()这两个核心函数。

从这两个函数的流程可以看到,资源加载使用到了Cache机制:

1.首先从AssetCache中查找,如果找到了,则更新Cache项的时间戳,并调用回调;

2.如果没有找到,则向AssetCache添加一个Request,然后启动Coroutine:CreateCachedAsset(),它的调用步骤是:

  • 调用AssetCache.StartLoading();
  • 启动Coroutine:CreateCachedAsset_FromBundle&lt;RequestType&gt;():
  • 使用AssetLoader.GetBundleForAsset()找到资源所属的AssetBundle;
  • 调用AssetBundle.LoadAsync()来真正加载资源;
  • 在加载的过程中,根据处理的结果调用:AssetCache.CacheRequest的OnLoadFailed()、OnLoadSucceeded()、OnProgressUpdate()等函数;
  • 在AssetCache查找此资源,如果找到了,则加载成功,调用回调函数;

调用AssetCache.StopLoading();

我们都知道在开发过程中,不能使用AssetBundle(每次启动都要打包,肯定收不了)。怀疑它的Editor模式相关的代码是用预编译宏处理来实现的,所以未出现在发布出来的程序集当中,类似这样:

  1. #if UNITY_EDITOR
  2. Obj = Resources.LoadAssetAtPath(assetPath, typeof(T));
  3. if (Obj == null)
  4. Debug.LogError ("Asset not found at path: " + assetPath);
  5. yield break;
  6. #else

复制代码

class AssetCache:资源的Cache机制

前面在AssetLoader一节我们已经讲到了AssetCache机制,这里再做一个详细的阐述。

前面我们已经讲到:

  • AssetCache中的资源项的时间戳,由AssetLoader在资源加载请求时维护;
  • AssetCache主要负责管理Cache数据,而真正的资源加载动作还是在AssetLoader中执行;

AssetCache的资源淘汰主要由外部的各个模块根据自己认为需要的时机去调用,例如:

  • SceneMgr.ClearCachesAndFreeMemory()
  • LoadingScreen.ClearAssets()
  • SoundMgr.UnloadSoundBundle()
  • 等等

另外,程序启动时会自动更新资源包(在Login.OnAssetsVersion()中启动),主要是通过UpdateManager和Downloader两个类来处理。

OK,总结一下炉石的资源管理机制:

  • 对游戏资源按照类型分包,买二手游戏每一类资源包可以有多个;
  • 在游戏运行时使用Cache机制;

《炉石传说》架构设计赏析(4):Asset管理相关推荐

  1. 微服务架构案例(02):业务架构设计,系统分层管理

    本文源码:GitHub·点这里 || GitEE·点这里 更新进度(共6节): 01:项目技术选型简介,架构图解说明 02:业务架构设计,系统分层管理 一.业务架构设计 1.基础概念 服务的架构设计决 ...

  2. 卫向军 | 从正交分解架构设计到矩阵式团队管理

    大家好,俗话说,早起的鸟儿有虫吃,非常高兴在新年之初与大家做一场矩阵式团队管理的交流分享. 今天的分享主题: <从正交分解架构设计到矩阵式团队管理> 带团队就是管人.管事.管钱.管心,合理 ...

  3. 《炉石传说》架构设计赏析(1):游戏启动流程

    今年的Unity Awards两项大奖颁给了暴雪的<炉石传说>,这真是对Unity一个再好不过的宣传了--你看,暴雪都开始用Unity了.大家都知道,目前Unity发布的游戏大多都没有对程 ...

  4. 《炉石传说》架构设计赏析(6):卡牌 技能数据的运行时组织

    前一篇文章我们看到了<炉石传说>的核心卡牌数据的存储,今天我们继续探索卡牌&技能. 主要的类 通过之前的分析,卡牌&技能涉及到几个类体系:Entity,Actor,Card ...

  5. c语言炉石传说算法设计,CCF-CSP题解 201609-3 炉石传说

    模拟. 注意随从的编号在\(summon\)和\(attack\)随从死亡时都可能改变. #include using namespace std; struct tNode { int attack ...

  6. c语言炉石传说算法设计,FZU Problem 2232 炉石传说(匈牙利算法)

     Problem Description GG学长虽然并不打炉石传说,但是由于题面需要他便学会了打炉石传说.但是传统的炉石传说对于刚入门的GG学长来说有点复杂,所以他决定自己开发一个简化版的炉石传说. ...

  7. c语言炉石传说算法设计,炉石传说:下棋吃鸡还扣分?设计师:现在已经改回去了...

    原标题:炉石传说:下棋吃鸡还扣分?设计师:现在已经改回去了 随着16.0补丁的上线,很多酒馆战棋的高分玩家发现了一件非常反常的事情.那就是补丁更新之后,赢一局不仅不加分而且会扣分(前四名),甚至于吃鸡 ...

  8. 《炉石传说》架构设计赏析(2):Scene管理

    今天我们主要分析一下炉石这款游戏中一共有哪些Scene,他们各自负责什么,以及它内部的逻辑.UI的处理方式. 在正式开始之前,我来对前文中提到的Scene切换再做一些补充分析.前文中我们看到Scene ...

  9. 《炉石传说》架构设计赏析(3):Gameplay初探

    经过前面的分析,我们已经找到了两个关键的类Gameplay和GameState(当然还有我最感兴趣的Spell和SpellController,这两个还要在后面分析). 首先我们看一下Gameplay ...

最新文章

  1. jQuery Masonry 一个 jQuery动态网格布局的插件
  2. 数据中心UPS电源节能降耗的四大原则
  3. boost::fusion::pop_back用法的测试程序
  4. Quick cocos2dx学习笔记
  5. 吴恩达机器学习:逻辑回归
  6. ipconfig显示IP地址情况
  7. BZOJ 2406 LuoguP4194 矩阵 有上下界可行流
  8. 计算机一级考试试题难不难,计算机一级考试通过率是多少 考试难吗
  9. 密码编码学与网络安全
  10. 计算机毕业设计之java+springboot基于vue的地方废物回收机构管理系统
  11. linux下的文件系统,Linux系统中常见的文件系统有哪些?
  12. 中通快递物流单号查询API接口免费对接案例
  13. 克劳士比语录(转载)
  14. 并发编程之深入理解java线程
  15. 显卡系列和种类你了解多少?AMD、NVIDIA显卡盘点
  16. Imagination 推出最先进的光线追踪图形处理器(GPU)
  17. 免费资源-成语答题小程序源码+教程
  18. python找到一行单词中最长的_如何在文本文件中找到最长的单词?
  19. 微信公众号可以改名称了,只限个人订阅号!
  20. 在使用tensorboard时报错tensorboard: error: invalid choice: ‘Recognizer\\logs‘ (choose from ‘serve‘, ‘dev‘)

热门文章

  1. 存储过程排版工具_我的绘图工具箱
  2. 14-爬虫之scrapy框架的基本使用01
  3. 10-异步爬虫(线程池/asyncio协程)实战案例
  4. oracle怎么查询表空间信息,查询Oracle表空间信息
  5. Tensorflow保存模型,恢复模型
  6. [TCP/IP] TCP如何保证可靠性
  7. BZOJ.2597.[WC2007]剪刀石头布(费用流zkw)
  8. Django两天搭建个人博客
  9. 删除排序数组中的重复数字 II
  10. bootstrap bable 自动换行问题