游戏开发论坛

 找回密码
 立即注册
搜索
查看: 36033|回复: 15

[讨论] [技术交流]不要用海量表项压垮“技能流程”

  [复制链接]

98

主题

784

帖子

4495

积分

版主

Rank: 7Rank: 7Rank: 7

积分
4495
发表于 2013-10-31 22:57:53 | 显示全部楼层 |阅读模式
  很多时候我们会把游戏中的很多东西压给技能,让技能负重累累,比如这个技能打中后产生的Buff的效果,流血、怎么表现的流血、流多少血、流多久等等这些都存在于技能表项中。其实从一个表的表项你可以看出一种思路,就像两军交锋可以从扎营看出主讲的排兵布阵能力,我认为这样过于负重的技能表项体现出来的是一种对于技能本身的曲解——技能,说穿了只是一个流程,而不该是一个实体。我们就详细深入地拆解WoW的技能流程,并且进一步看如何引用到我们的游戏中去。

1,技能的基本流程,也就是技能的本身。

skillprocedure.png

  先看这个流程图,玩游戏的电脑上没有装Visio,于是就用小画家凑合了一下。这个流程中,绿色的部分代表客户端的,而红色的部分代表了服务器,其实不必太在意他是服务器还是客户端,只是既然我们用WoW的举例,就要还原出他的CS的特性。

1)[c]接收到释放技能的input,就是玩家通过按钮、宏等方式申请释放技能。

2)[c]技能准备阶段,是客户端先行的做法,客户端会预先播放一些准备的动作,当然很多距离的判断也会丢给客户端,虽然科学的说这不好,但是事实上这很有效很棒。在这个阶段如果是需网络的游戏,还需要做一个判定是否发送给服务器,频繁的发送是会轰爆服务器的。

3)判断技能条件是否满足,在WOW中包括蓝条、能量条等是否足够,距离是否OK,目标类型是否对路等等判定。

4)[c]如果技能无法释放,服务器告诉客户端后,客户端终止准备阶段的动作,并且提示错误。

5)[c]服务器和客户端的吟唱阶段,在WOW中很多技能会有吟唱阶段,比如术士的暗影箭就会进入两手冒黑光的阶段。瞬发技能可以跳过这个阶段,在这个阶段中可以设计打断类技能来终止流程等。

6)[c]吟唱完毕后2次检测条件是否满足。

7)技能正式准备释放,服务器告诉客户端可以播放后面的事件了,而自己则根据目标类型等因素获得对应的回调函数参数,并传递给下一个流程——也就是调用策划的脚本,来完成整个技能流程的使命。而这里对于通常理解的技能概念来说,只是一个开始。

8)[c]客户端收到可以释放的信标,则开始释放对应动作,并顺利完成这个技能的释放流程。

9)服务器调用策划对应的脚本函数,你可以看到这是进入了另外一个流程,在这里会有多少种结果,谁都不知道,连策划都不一定知道,因为想法总是在不断扩展的,加入我们抛开合理性看,一个技能能让目标直接下线也是应该要去做到的,因此需要提供出让角色下线的接口。而通常情况下,这里的功能大多是——产生一个AOEObj,对目标产生BuffObj,直接生效另外一个流程。好吧,前面标上了中括号s就成了删除线了,所以干脆前面不标东西的就做服务器端的解释了。其实到这里为止,整个技能就算是完工了,因此技能只是一个流程,而对应于这个流程,策划需要设计的基本表项的DSL结构就是:

客户端
  1. type c_skill{
  2. id:Int; //这你一定用得着
  3. name:String;
  4. icon:String;
  5. targetType:Dynamic;//目标类型,实际上这个定义方式很多,所以这里就用dynamic偷个懒。
  6. prepareAction:Action; //我们将一组动作包含特效定义为一个Action,假如要通俗的举例,你可以理解为CCSequence,这里是准备阶段释放者的动作。
  7. castingAction:Action;//吟唱阶段
  8. releaseAction:Action;//释放阶段,值得注意的是,这里只是动画,一定要把持住这个概念。
  9. }
复制代码

服务器端
  1. type s_skill{
  2. id:Int;
  3. targetType:Dynamic;
  4. condition:*Character->[Bool];//我们把释放条件定义为一个函数,传入角色指针,返回布尔(满足否)
  5. effect:*Character->Dynamic->[Void];//这是技能释放的效果,除了传入释放者指针,Dynamic用于不同释放目标时采用不同类型的参数,但是这里有一点我要吐槽一下,除了写底层外,像我的这个地方这样写就是一个错误,逻辑代码中不推荐采用 xxx is xxx这种类型判断的写法,常用OOP的人一定会有这个概念问题。
  6. }
复制代码

  以上我们可以看出,针对不同的环境,表项内容是不同的,但是都有ID作为连接标识。最关键的是,这样的表项,连10列都不到。

2,技能的效果与典型的极易产生混乱的用法。

  在我们说到effect的时候,其实如果你细想下去,在应用的时候的确是会存在一些麻烦,加入你之前了解过我的AOE和Buff机制,这里反而更容产生一些误区,实际的例子之一就是:

  我的技能仅限男性角色使用,效果是释放出一个白色的球体,命中目标后堆叠一层buff,当Buff层数达到一定层数时,若目标为女性,则会昏迷3秒(好吧,你要想歪也正常,谁让咱策划素质都很差呢?)

  其实这是一段糟糕的技能描述,通常会在项目中带来合作问题,具体问题在——你的白色球体的作用描述不清,是的,乍一看说的很清楚啊,但事实上缺乏关键信息——他是一个什么样攻击范围的技能,他的生效时间是否很严谨?这里会产生的分歧——

1)如果是一个对单体的目标,那么你很在乎它的生效时间么?我是说在客户端表现下,因为延迟会产生一些小麻烦,这不是关键,关键是,如果他有飞行轨迹,并且飞的比较慢的时候,目标中招的位置很重要吗?确切的说,我“猜”很重要,因为会导致目标昏迷。事实上实现的时候这里的分歧在于,如果位置不重要,你可以直接作为另外一个函数来执行,而如果很重要就麻烦了。

2)如果目标受到技能影响的位置很重要,又引申出另外一个问题,他的范围是怎样的,我们知道LoL中小法师的Q技能,那个球如果你死命逃,最后逃不掉,但是会延晚你中弹的时间,虽然是很罕见的现象但这一定存在一个可能——原本我要死了,可是我跑得够快以至于奶上来了,我中弹了却活下来了。如果是这样的技能,很显然我们应该在游戏中设计一个BulletObj,当然这可以用Buff来实现,但如果你真的追求这么严密的效果,你还是应该产生一个子弹去追踪目标,然后将一些信息丢给子弹,当子弹命中后才执行效果函数。那么假如这个技能是一个指向性技能?

3)指向性技能又存在2个情况:如果是炸弹人的炸弹,其实是在你释放的时候会炸到哪儿我早就知道了,但是生效的时间会有延迟,而这个延迟我也知道,因此产生的是一个固定位置的AOEObj,而假如如同EZ、爱射的大,则我们需要一个移动的AOEObj。

  这些问题的产生并不是刁难设计者,而是设计者本身并没想清楚这些细节,所以设计不出好技能。那么抛开这些,我们还有一个问题就是,这个技能的效果如何实现?好吧,你该回顾一下我说的Buff机制,我们得有一个白液的Buff,这个Buff在occur的回调中,判断当前层数和目标性别,决定是否上另外一个昏迷的buff就好了,非常简单。


  其实你不难发现,真正成为一个你看起来很复杂或者很有趣技能的是buff机制和Aoe机制,而技能本身更象是一个Trigger,所以技能本身就只是一个Procedure,作为策划,首先要从概念上把你肉眼看到的,别人游戏中的技能拆成这样的碎片,你才能有效地组织并设计出更好的技能来。

2

主题

60

帖子

418

积分

中级会员

Rank: 3Rank: 3

积分
418
发表于 2013-11-1 00:54:55 | 显示全部楼层
本帖最后由 by2120102707 于 2013-11-1 08:47 编辑

说下我的看法
1、表的作用实际不是定义流程,而是提供流程中需要的数据。因此不管流程需要数据的是前端还是后端,他们都应该从一个表中调用。
2、并不是因为把技能作为实体才导致它的混乱,真正导致混乱是的技能实体的范围扩大化了(从这个意义上说,把技能做为一个流程也没什么错,技能的承载内容应该仅仅是这个流程本身),把后续效果剥离出来会好很多。

我个人的经验,不评价好坏,大概是这样的:技能的表象数据必须要有,技能效果相应的数据应该仅限于这个技能释放条件和它的直接效果(这个与表象共享技能id,所以最好也放在一起);直接效果之外的触发效果,单独建立BUFF表,为此建立一套单独的流程,供技能调用(也就是技能效果应该是触发了某个buff)

1

主题

35

帖子

154

积分

注册会员

Rank: 2

积分
154
发表于 2013-11-1 01:52:12 | 显示全部楼层
现在计算机这么牛B,能不能所计算的过程留在客户端,只把结果反馈到服务器。

2

主题

60

帖子

418

积分

中级会员

Rank: 3Rank: 3

积分
418
发表于 2013-11-1 02:12:18 | 显示全部楼层
huangping1987 发表于 2013-11-1 01:52
现在计算机这么牛B,能不能所计算的过程留在客户端,只把结果反馈到服务器。 ...

这不是给外挂和修改器形成方便了么......

0

主题

185

帖子

728

积分

高级会员

Rank: 4

积分
728
发表于 2013-11-1 09:13:45 | 显示全部楼层
前半段纯理论,感觉就是在讲大道理:对肯定是对的,只不过对实际应用没有帮助。

后半段的那个例子很实在。现实中也是常碰见这类的问题。如果我们的策划愿意认真学习这部分内容,那对自己和他人的工作帮助很大。

62

主题

1976

帖子

2657

积分

金牌会员

Rank: 6Rank: 6

积分
2657
发表于 2013-11-1 15:00:19 | 显示全部楼层
不明觉历

0

主题

80

帖子

890

积分

高级会员

Rank: 4

积分
890
发表于 2013-11-1 15:38:34 | 显示全部楼层
我们是这么拆开来做的~

0

主题

256

帖子

1559

积分

金牌会员

Rank: 6Rank: 6

积分
1559
发表于 2013-11-1 16:45:29 | 显示全部楼层
为什么总喜欢抢程序的活,虽然能做的快一点,可程序不就没有成长了么

1

主题

15

帖子

111

积分

注册会员

Rank: 2

积分
111
发表于 2013-11-4 11:44:09 | 显示全部楼层
by2120102707 发表于 2013-11-1 00:54
说下我的看法
1、表的作用实际不是定义流程,而是提供流程中需要的数据。因此不管流程需要数据的是前端还是 ...

有道理,mark下。

0

主题

8

帖子

91

积分

注册会员

Rank: 2

积分
91
发表于 2013-11-4 14:11:51 | 显示全部楼层
策划真正苦恼的是,为什么要设计成这样?
唯一靠谱而又无用的答案是,为了差异性。虽然是模仿的
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-6-8 15:49

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表