181443gzaafhgq5a3znscq.jpg
  GameRes游资网授权发布 文 / 傅建钊

  新手引导确实是个麻烦事,逻辑杂乱,而且跟界面的逻辑常常交叉在一块,弄的不好的话代码里到处都是if else,保存各种临时状态变量。但这里面其实也是有规律可循的,不说完美解决了所有问题,但至少可以提供一个框架,一种问题解决的思路。这里面有3个关注点:

  1.引导的触发点

  2.引导的进度

  3.引导的表现内容

  传统的方案实际上也是在解决这3个问题,只不过用的是生硬粗暴的硬插的方式去编写代码,代价是容易出现bug,不好维护,而且几乎不可复用。

  就像把状态机转化为行为树一样,思想上需求去抽象各个点,然后让它们有机组合起来,形成一个模块,加入说是新手引导模块。

  假设这个模块叫做Guide,下面分别阐述以上3个问题的解决方式。

  1.新手引导的触发点,一般新手引导是在界面切换后发生的,那比如这个界面有个OnEnter,那一般界面都会有一个基类,所以我们可以在这个基类的OnEnter里注入一句Guide::Instance().Trigger(...界面名称等参数),当然我们也可以在其他界面统一调度的地方去调用这个Trigger。有时候也可能需要在游戏帧里去调用Guide::Instance().Update(dt)。这一点上,不一样的地方在于以前是硬在各个界面里写触发,现在是在统一的地方写,数量上明显少了。

  有触发入口了,然后到底是否要触发引导?这个时候就需要Guide里维护一个Trigger列表,简单比如说是List<ITrigger*>,每一个ITrigger上有一个断言方法bool CheckCondition(...参数自己定),这样简单来说,你只要遍历这个Trigger列表的CheckCondition方法,就可以实现条件触发了。而里面的CheckCondition的实现,简单的可以直接查询Player的属性来定(比如说到10级才触发),或者当前判断当前是在什么界面,复杂的甚至可以用IPredicate,AddPredicate,OrPredicate,NotPredicate来实现一棵条件判断树,也可以触发脚本。游戏在启动的时候会通过配置或脚本加载这么一个trigger列表,已经触发的Trigger可以从列表中删掉。

  ITrigger想要实现的话可以支持嵌套,变成一棵跟行为树一样的结构。

  2. 引导的进度,有些引导进度是根据玩家属性相关的,比如玩家等级,这个不需要专门保存。而有些引导步骤进度通常需要保存,这些可以在服务器数据库(网游)或客户端存档(单机的话)保存一个引导表,每一行有引导Id(对应Trigger),进度Index,再附加内容。已经完成的引导可以从玩家上标记。如果只支持引导按序触发的话,那玩家身上可以保存一个当前引导Id,可以加快不少效率。如果支持非线性触发,那就从引导记录上做标记也可。

  3.引导的表现内容,一般引导的内容就是切换界面,禁止一些按钮等等,这个在ITrigger的Run里来实现,可以由你发挥了,看是直接在里面写UI或者触发脚本什么的。

  这样下来,就把引导的逻辑和界面逻辑隔离开了,不过实际上因为引导是强关联到界面的行为的,所以在实现引导的时候,也经常需要获取当前界面的某个按钮等等操作,不过至少清晰可维护。

  这个方案我自己以前实践过,还算能满足需求。

  相关阅读游戏新手引导设计要点分析
锐亚教育

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