1.什么是引导
每款游戏由于题材、玩法等各种问题存在一个新手教育期。新手引导的作用就是将游戏的规则、玩法以简单的形式在较短时间内传递给用户。
2.为什么要有引导框架
新手引导和游戏的业务逻辑紧密相关。为了降低代码的耦合性、面向配置让策划可操作,所以有了新手引导框架。
3.引导方案
3.1 节点和步骤
新手引导模块由许多节点构成,这些节点可以前后有序也可以互不影响。初始化的时候我们通过服务器返回的二进制数来确定哪些已完成哪些未完成依此了解玩家新手引导进度。
每个节点由多个引导步骤构成,每个步骤由策划配置,步骤之间也可以是有序和无序。由于节点的第一步不能为自动触发,所以初始化的时候触发器只关注节点的第一个步骤,第一步完成后再对整个节点的步骤进行遍历。如果是有序则监听下一个节点。如果有无序的则同时监听。不管有序无序,每个节点只有一个最终步骤。完成该步则该节点完成。
3.2 容错
容错是新手引导框架的重要部分。由于网络、配置、代码错误等种种原因可能会导致引导模块中断,特别是强制引导如果中断很有可能导致用户界面卡住。
本框架的容错类型分为:
- 非法界面容错:强制引导时出现非法界面或依赖界面被关闭。在框架初始化的时候就注册UI界面显示和关闭事件,当步骤的触发器触发时将监听状态设为true然后进行检测,如果是强制引导并且当前界面和引导忽略界面与依赖界面不符则进行容错处理。在节点完成后将监听状态设为false
-
强制引导焦点大小为0或屏幕外:强制引导当前屏幕没有可点击区域。在已显示当前步骤的引导界面后,设置为检测状态。首先获取强制引导矩形点击区域(该函数在强制引导界面逻辑中实现),如果点击区域宽高小于5或者该区域不在UI摄像机内并且5s后仍没达到要求,则进行容错处理。
- 强制引导时间超时:在引导完成后的过渡界面停留时间超过限定时间。在完成当前步骤执行完成逻辑时进行检测。如果完成当前步骤但当前页面在设置时间内没有关闭(框架内默认时间为30s),进行容错。
-
lua报错:执行配置表中的回调函数出现的lua代码错误。在框架初始化时使用AddListeningLuaException进行监听
- 自定义容错:引导界面逻辑中自定义出现的错误。执行引导界面逻辑时出现的错误,如果出现直接进行容错。
容错方式:跳过当前步骤、跳过当前节点、不做处理。
3.3 模块
a.触发器
触发引导流程。检测类型有:
- Auto: 自动触发
- Event:事件触发
- OpenUI:打开指定UI触发
- RecvMsg:接收指定消息触发
每次触发时根据触发类型检测,如果满足条件,并且容错没有问题。则执行当前步骤。
b.执行
用于执行引导步骤。如果配置了BeforeExecute则首先执行。如果定义了OverrideExecute则在显示引导界面后执行。
c.完成
结束当前步骤。检测类型有:
- Auto:自动完成
- CloseUI:关闭指定UI
- Click:点击指定按钮即完成
- Event:接受指定事件完成
- RecvMsg:接收指定服务器消息完成
触发后,根据类型完成检测。如果设置了延时完成,会根据所设参数进行延时。如果当前步骤是第一步,则对当前节点所有步骤遍历,如果都是有序的则触发器只会监听下一步,否则会监听所有非有序步骤。如果当前步骤是最后一步,则完成当前节点。
d.策划配置表
引导的所有步骤是由策划配置完成的。主要配置各个引导步骤模块的参数,节点之间的顺序关系也是在这配置的。每一个步骤可能包括:
- Tag:基础属性
- view:引导界面配置
- Trigger:触发器配置
- JumpCheck:跳转检测
- Execute:执行引导
- Comp:完成的相关配置
- Error:容错配置
具体请看SysGuideTest
4.源码实现
4.1 框架执行流程
-
初始化
- 收到服务器消息后,根据服务器发送的二进制数判断有哪些未完成的节点,有序则触发器监听第一个节点的第一步,无序则同时监听多个节点。
- 调用容错的listening开启所有容错的监听。
- 初始化行为,这个行为可能包括相机、人物的位置等。视项目而定
-
触发
- 界面出现某些行为触发了某个步骤的触发器。触发器按类型检测
- 如果当前步骤是第一步,则对该节点所有步骤遍历,监听有序第一步以及所有无序步骤
- 进行跳转检测,根据配置表所配OverridFunc和ExFunc来决定跳转到哪一步
- 如果没有跳转,则进行容错检测。
- 开始执行引导步骤,调用GuideMgr.Playing。
-
执行
- 配置了BeforeExecute,先执行展示GuidePanel引导界面,如果有OverrideExecute则在引导界面中执行该逻辑
-
注册该步骤的Comp加入监听
-
完成
- 触发某步骤的Comp回调,执行检测,如果符合条件。进入CompStep方法开始完成逻辑
- 设置了delayComp,则延迟相应时间,时间到后执行回调
- 回调函数中进行容错检测
- 发送埋点信息
- 配置了ExFunc则执行
- 是最后一步完成该节点,如果是顺序的话触发器监听下一个步骤。
-
强制引导的实现
当步骤类型设置为Force并且设置了View.ForceAttri属性,该步骤就是强制引导步骤。
使用全屏遮罩盖住页面所有元素,在遮罩上放一个按钮遮罩,按钮遮罩的颜色、大小效果、位置、图片等都可以通过配置文件配置。按钮的点击事件由View.clickHandler实现。通过GuideGlue胶水传递。如果配置的是函数,直接赋给按钮的点击事件。如果是字符串,则通过此名称查找依赖界面元素并将对应点击事件赋给遮罩。
4.2 UML图
5.关键点,重要节点,疑难杂症场景
如果出现引导过程中报错,直接发送协议,完成这个引导。
5.1 容错处理-Lua抛出异常
在Main.lua中有一个exceptionHandlers异常函数列表,只要抛异常,就会把这个列表里面所有的异常报告函数执行一遍。引导启动的时候,向异常列表中注册一个异常报告,目的是,一旦发生异常报错,就会告诉开发者,这个报错,是在引导运行的时候报的错。
5.2 容错处理-弹出非法界面
监听界面的打开事件,一旦有界面打开,就检测是不是本次引导绑定的界面,不是就报错
5.3 容错处理-强制引导无有效焦点
检测引导需要点击的rect范围,是否在Camera范围内。
5.4 容错处理-连续强制引导过渡超时
超过30s没通过,就报错。
5.5 容错处理-断线重连无法触发RecvMsg
如果引导在等待RecvMsg协议的返回,此时断线重连,则RecvMsg不会回了,此时执行一下jumpCheck,跳过这个等待阶段,并抛错误。
5.6 容错处理-自定义错误
其他引导的地方需要抛错误,就用这个自定义的名义来抛GuideDef.ErrorCode.UserDefine