今年的Unity Awards两项大奖颁给了暴雪的《炉石传说》,这真是对Unity一个再好不过的宣传了——你看,暴雪都开始用Unity了。大家都知道,目前Unity发布的游戏大多都没有对程序集进行混淆、加密,所以作为一个炉石的玩家&Unity的初学者,自然不能错过这个机会。让我们好好看一下暴雪的代码吧。炉石传说的游戏内容的非常丰富多彩,所以我花了一些时间分析了其程序集,将一些设计思路记录下来,与大家分析。

做这些分析的主要目的是:

1.看看炉石如何组织游戏逻辑,以支撑复杂的技能逻辑、表现等;

2.看看炉石是如何使用Unity的,其结构设计和技巧上有什么值得学习的地方;

3.向暴雪的程序员好好学习一下英语。

下面我们就正式开始。我习惯先分析一下游戏的启动流程,这中间就涉及到了游戏基础数据的管理&初始化,各种管理器级别的类,以及相互引用关系也会初步显现。

首先看一下我找到的一些游戏启动过程相关的类,下面是他们的类图:

接下来我们分析一下游戏启动的操作流程。

  • ApplicationMgr对象应该绑定到了一个场景对象中,这个场景应该在游戏启动中加载;
  • ApplicationMgr:Awake()被Unity引擎自动调用;
  • 调用ApplicationMgr:Initialize(),在这个函数中顺序调用了以下成员函数来进行初始化:
  • InitializeMode():设置模式为ApplicationMode.PUBLIC;
  • InitializeUnity():设置了UnityEngine.Application的一些属性;
  • InitializeGame():看来核心的内容在这里,初始化Network,GameMgr等;
  • InitializeWindowTitle();
  • InitializeOptionValues();

游戏启动应该不只这点东西。由于我们纯靠程序集的动态分析,无法知道它的场景编辑、对象的脚本绑定,也不能跟踪调试,所以只能靠猜测了。另外,一些事件是通过网络消息触发的,这也给静态分析带来了一些难度。

OK,我们继续。我注意到了class Login,它从Scene派生。查看了一下Scene的派生类还有不少,我猜测每个派生类,作为特定Scene逻辑处理的脚本。而Login应该是在第0个场景中被激活运行。我们看一下Login:Start(),这属于MonoBehavior自动调用,他主要做了这样几件事:

  • 注册了一些资源版本检测、Login相关的网络消息回调;
  • 通知SceneMgr场景加载完成;
  • 调用成员函数:AutoLogin();此函数调用Network.AutoLogin();

从配置文件中找到User Name,然后调用ConnectAPI.AutoLogin()——奇怪的是发现这个函数只是简单的返回false,并没有进行实际的操作。

我们在来看一下Login:Update(),这个也是属于被自动调用的脚本函数。在这里它检测了Login的状态,并调用了成员函数LoginOk(),而它有主要调用了AssetsVersionCheckCompleted(),这个函数内容很丰富:

  • 通知其他模块,已经登录成功,包括:BaseUI、InactivePlayerKicker、HealthyGamingMgr、GameMgr;
  • 调用一些模块的Initialize函数,包括:DefLoader、CollectionManager、AdventureProgressMgr、Tournament、StoreManager等;

我们前面看到了Login从Scene派生,并且还有一个SceneMgr类。我们可以断定游戏根据不同的逻辑划分成了一些scene,接下来我们就探索一下Scene切换的流程。还是从Login入手。

以下流程都是在Login类中完成,下面描述的过程都是Login成员函数的调用:

  • 首先我找到了Login:OnNetCacheReadyStep2()函数,这个应该是login流程中某一步的网络消息回调函数;
  • 它会调用WaitForAchievesThenInit()这个Coroutine函数,这个函数检测了是否需要播放视频,然后调用ReconnectOrChangeMode();
  • 此函数处理重新连接,一般的话应该是调用了ChangMode();
  • ChangMode()处理了新手教程相关的启动逻辑,一般的话会调用ChangeMode_Hub();
  • 这个地方貌似是调用了一个技能特效,特效播放完成之后调用回调函数:OnStartupHubSpellFinished();
  • 此函数调用ShowUnAckedRewardsAndQuests();
  • 这里面主要是调用了HandleUnAckedRewardsAndCompletedQuests(),哦~,这应该是游戏启动的时候显示当前任务还有未领取的奖励的那个界面;
  • 它会调用ShowNextUnAckedRewardOrCompletedQuest();
  • 其中主要调用了ShowWelcomeQuests();
  • 当幸亏显示的任务为0时,则调用了这一句:SceneMgr.Get().SetNextMode(SceneMgr.Mode.HUB),这是关键的一步了;

接下来就我们跳转到SceneMgr类中,二手游戏出售继续探索Scene切换流程的实现。以下都是指的SceneMgr的成员函数:

  • SetNextMode()函数主要就是把“m_nextMode”成员变量设置为了指定值;
  • 接下来看一下Update(),这个函数主要是检测了是否需要切换Mode,然后调用了:

SwitchMode():这个是一个Coroutine,它主要是调用了LoadModeFromModeSwitch(),它的核心也是调用LoadMode();

直接调用LoadMode()

  • LoadMode()函数,主要是根据当前的Mode,调用LoadScene();
  • LoadScene()函数主要是调用了:Application.LoadLevelAdditiveAsync(this.sceneName);

这样就完成了场景的切换。

OK。通过以上分析,我们大体了解了游戏启动过程是这样的:

进行账户验证;

账户验证完毕之后,显示未领取的奖励和任务;

然后切换到SceneMgr.Mode.HUB模式,即加载了相应的Scene。

关于游戏启动的分析告一段落,下一篇将会分析一下炉石的Scene组织。

《炉石传说》架构设计赏析(1):游戏启动流程相关推荐

  1. mac玩炉石传说体验怎样_我可视化了自己玩过的《炉石传说》中每一个游戏的数据。 全部4,700。...

    mac玩炉石传说体验怎样 by Alan Wilson 通过艾伦·威尔逊(Alan Wilson) 我可视化了自己玩过的<炉石传说>中每一个游戏的数据. 全部4,700. (I visua ...

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

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

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

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

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

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

  5. 云游戏流媒体整体架构设计(云游戏流媒体技术前瞻,最近云游戏概念很火,加之对流媒体技术略有研究,简单写一些)

    前言: 遥想当年阿法狗战败一众围棋国手,风气一转,似乎所有人都懂AI.这次谷歌又放出了stadia,国内鹅厂再次跑步进场,贵州某xx云提前布局. 闲来无事,尝试体验了一下贵州某xx云的云游戏(不打广告 ...

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

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

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

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

  8. cc.game对象和游戏启动流程

    cc.game是Cocos2d-JS的游戏对象,主要职责包括,配置的读取,引擎的加载,游戏脚本的加载,以及游戏的启动. cc.game对象目前的设计非常精简,使用也非常简单,开发者需要关注的只有非常有 ...

  9. 架构设计 | 基于电商交易流程,图解TCC事务分段提交

    本文源码:GitHub·点这里 || GitEE·点这里 一.场景案例简介 1.场景描述 分布式事务在业务系统中是十分常见的,最经典的场景就是电商架构中的交易业务,如图: 客户端通过请求订单服务,执行 ...

最新文章

  1. Hessian的使用以及理解(转)
  2. mysql 基础选择题_mysql基础12(mysql练习题)
  3. 爬虫python下载视频_用python做爬虫下载视频
  4. 【IBatisNet Spring.Net】ORM与IOC 简单配置
  5. 【转】项目面试-如何介绍自己的项…
  6. iOS限制文本输入长度进阶之 一
  7. 【exp-linux】用aplay直接播放音频文件(mp3,wav)
  8. 达梦数据库(DM8)初次使用及DCA考试体会
  9. #小米游戏盒子 #小米笔记本驱动 @FDDLC
  10. visio画箭头时,如何去掉箭头的自动连接连接点(吸附)功能?
  11. HTML5期末考核大作业,个人网站—— 程序员个人简历模板下载HTML+CSS+JavaScript
  12. 代数结构入门:群、环、域、向量空间
  13. day04,字典的操作
  14. 数据结构第1章绪论相关练习题
  15. 深度学习笔记(一)了解深度学习
  16. 查询 IEEE 期刊往年影响因子以及趋势
  17. 无线局域网技术(二)无线传输技术基础
  18. 如何一键重装Win7系统 Win7系统重装的方法教程
  19. 小米商城侧导航栏的实现(导航栏的制作)
  20. 【STM32 .Net MF开发板学习-19】DHT11温湿度传感器通信(上)

热门文章

  1. php session_start() 非常慢,php – session_start似乎很慢(但是有时候)
  2. gcc编译python可执行_如何运行Nuitka编译的Python可执行文件
  3. redis和mysql实现原理_redis和mysql结合数据一致性方案
  4. 机器学习:使用numpy实现数据增强(Data Augmentation)
  5. bootstrap学习(一)栅格、布局
  6. Mysql数据库中制作千万级测试表
  7. [CSS] Target Positional Elements Using *-Of-Type CSS pseudo-classes
  8. 04JavaScript中函数也是对象
  9. Home-brew 安装卸载 Git
  10. 09 | 基础篇:怎么理解Linux软中断?