« 键盘毕竟不是手柄 | 返回首页 | 显卡还是 N 卡好啊 »

角色动作控制接口的设计

最近一段时间工作的侧重点转移,我从服务器的设计转到客户端这边来。

自从最底层引擎的架构完成后,我们的客户端留了两个人在全职写代码,一个人负责 C 层面的 3d engine ,另一个人负责设计高层面的应用接口,并在此基础上完成游戏 demo 。

从程序员角度上看,人都是相当不错的。要设计有设计能力,有编码有编码能力。代码审美观上大家也很一致,所以我们几个人一起工作的很愉快。

唯一美中不足的是,做 demo 的程序员游戏接触的太少,所以在操作手感调整方面有点相形见绌。需要经常性的跟负责战斗动作系统的策划沟通调整。而策划毕竟不太明白程序背后再用怎样的方法实现,最终还是有点不尽人意。如果有足够的时间,倒总是能调整好。不过现在项目进度比原来计划有所提前,我就直接参于进来参合了。加快这方面的开发进度。

上周花了几天时间通读了所有相关的代码,整体设计还是不错的。不过这两天用下来,还是觉得有点别扭。

我希望游戏能有比较流畅的操作感,可以灵活的操作游戏角色做出各种动作,包括战斗时的腾挪,组合技能等。写了不少脏代码尝试我希望的手感时,终于发现一些设计问题了。

所谓操作手感,其实不仅仅在于对输入设备的控制。它包括输入设备(键盘鼠标)的数据采集分析和输出设备(显示器)做的视觉反馈。希望获得良好的手感,就一定要准确的控制每个动作的视觉反馈。

这里,3d engine 的角色动作控制接口设计就很重要。需要做的简单易用,又能保持健壮。

其实到了这个层面,已经不关乎 engine 是 2d 还是 3d 的事了。只是 3d 在精灵的空间位置和摄象机的控制上,比 2d 多出一个自由度来,运用要复杂很多。保持接口简洁就更为困难了。

今天暂时先谈谈简单的部分,如何控制角色的动作播放。(2d engine 也用的到)

本质上,图象 engine 是一帧帧渲染角色精灵的。渲染这个操作必须被隐藏起来为应用层不可见。3d engine 有更高的表现力,比如可以做骨骼动画,以此做动作间融合。这些应该归到渲染层面做。绝大多数情况下,应用层不应该关心。

以前,我们的引擎接口提供了方法设置角色当前应该播放的动画系列。其参数有播放指定次数还是循环播放。仔细考虑,其实不太合理。

实际应用中,将角色动画播放指定次数完成后,引擎应该做什么?让精灵的画面停留在最后一帧吗?显然是不合理的。如果精灵全部是模拟的活物的话,正常状态下它们永远都应该在运动。

接口设计的健壮性应在于,我们无论怎样调用,都不应出现错误的状态。角色的画面静止就是这样一种错误状态。

我曾经想实现一个很复杂的动画序列驱动引擎,相信很多人也干过。就是在引擎中支持播放一个列表的动画序列,并可以为每个节点附加控制器,决定是反复播放还是单次播放。并让控制器可以控制角色的内部属性。甚至这个播放列表还可以是树状结构。

这个想法大约在 01 年的时候我曾经实现出来,发现并不好用。它完全违背了 KISS 原则。越是将功能做的全面,就越难二次扩展。用它的程序员也很难控制内部细节。(btw, 我在去年初放弃 boost jam 而换用 gmake 做 build tool 也是因为类似的理由)

如果真正的考虑,其实我们所有需要控制的角色动画其实都可以分解成这样一种元动画:即一组循环动画前置一个进入这个动画的引导动画序列。比如坐下,就是从直立状态经历一个坐下的过程,最终让角色一直持续在坐着的状态。又比如人物站立时,做一些花哨的手势,也应在完成之后,又恢复成普通的站立形态。

至于前导动画系列怎么和之前的角色状态衔接,我们可以交给引擎的底层考虑。而一切复杂动作皆可被如上分解。及时有一些特例,也可以做一些变通。比如最终的循环播放阶段可以只有一帧,那么角色就静止在那里了。

如此设计,我们并不需要让引擎提供接口去控制一组动画需要播放一次还是多次,或是不停播放下去。对一个动画元组永远都只有一个播放指令。

那么,交互式的动画如何控制?

这需要增加一个调用参数。虽然,一组动画总可以无限播放,但引导这段动画的前序动作却只有一次。使用回调函数的设计是很难看的。比较漂亮的方法是可以指定前序动作的时间长度。因为这个时间往往跟逻辑紧密相关,比如挥刀劈砍,完成整个动作的时间需要程序控制精准,而不能由着美术人员制作。许多动作的播放时间长度都会随着游戏开发不断调整,我们不可能每次调整都去要求美术人员改变。所以引擎应该内部支持动画序列的播放时长,按程序运行时参数要求拉伸或压缩。

对于循环播放的动画有时也有必要精确控制每个循环的时长。最典型的例子是跑步动画。当我们设定为角色一秒跑动两步跨过 10 米时,就需要精确控制 0.5 秒播放一个跑步循环。这样的控制可以避免视觉上感觉角色在虚拟世界的地面上滑动。

总的来说,游戏逻辑应该和画面脱离。时间控制是放在逻辑上的,而画面表现则配合逻辑实现。

Comments

循环动画是可以被中断的,但是不会发生事件。非循环动画是循环动画中插入的新动画,播放完毕会发出一个事件。 这个事件的发出是逻辑层预先根据动画的播放时长来计算出回调时机,总觉得不如动画播放完毕告诉你来的放心啊, 但是给动画绑定一个回调也觉得累赘。看来没有什么完美的设计,只有你觉得合适的才是好的
我的思路和楼上很像, 把动作分类为state和action,state一般是循环动画,action一半是非循环动画。 让底层支持同时走多个动画轨道,但是表现出来的只有优先级最高的那个,action的优先级比state高。 这样,如果我需要坐下,只需要同时播放由站到坐的动作,和坐在地上的状态动作,就可以了
现在很怀念DOS时代的一些游戏,比如吃豆、水管工等,比现在的一些大型游戏还玩着有意思。
游戏主要是要好玩,现在一窝蜂开发3D游戏就是个错误,3D游戏提高了游戏开发的门槛,但是实际玩起来不怎么样,网易为什么不做2D或2.5D游戏,这样会把主要精力放在怎样让游戏好玩上面,而不是像现在这样在技术层面上折腾。
关于引擎,我觉得要分两部分:一部分是图形底层,一部分是简单逻辑部分。 图形底层完全不必要知道有动画循环这样的概念,是一个无状态层。无状态就是说,没有前因后果,不会因为某次绘制指令而改变内部状态。这样有利于数据共享。这部分每次就接受绘制参数进行绘制,其中,很关键的时间参数,不是多少多少毫秒,就是一个[0,1]之间的浮点数。这样,从底层上就剔除了美术给出的动画时间长短的问题。当然,这部分还是可以查询出美术的动画长短的。 另外一部分,具备状态的部分,有非常简单的时间流逝功能,一个动作完成了,可以选择循环播放,也可以选择暂停在最后一帧,取决于项目逻辑。通常情况下,播放完毕后应该触发一个通知,让项目逻辑去处理。一般,我推荐使用查询方式来做——可以少掉很多循环引用管理的问题。 另:关于动画带位移如何处理的问题,正在苦恼中。一方面希望项目人员能省心些,一方面也希望引擎人员身心写,还要照顾美术人员的习惯感受——很不容易啊
看到时候就感觉似乎有些疑问 3楼似乎说到了关键。 用时间去同步事件,总给人一种用sleep同步线程的感觉(夸张了-_-!)
听各位高手聊技术问题,真是一种享受!
这种方式在 war3 中早就采用了。 暴雪出品的游戏的品质就是一流的,国内外许多游戏公司做来做去,仍然达不到暴雪几年甚至是十几年以前的游戏开发水平。 如果说到操作性,PC 机游戏中算得上一流的基本上都是竞技游戏,比如 CS, starcraft, war3, 这些游戏都是使用键盘和鼠标操作,在操作感上相比游戏手柄没有丝毫逊色。 格斗类和过关类的游戏更加适合使用手柄、操纵杆等设备。强调故事情节的 RPG 对操作要求不搞,采用手柄或鼠标加键盘都可以。动作 RPG,在 PC 机上一般都是鼠标加键盘,在电视游戏机上则是手柄。 我从来都不认为键盘+鼠标的操作性没有手柄好,顶级的 SC 或 war3 玩家的 APM 几乎都在 200 以上,这样的操作数与手柄相比是过之而无不及。选用何种设备关键要看游戏类型、机种等场合,每种设备都有各自的特点。 我也是疯狂的游戏玩家,小时候喜欢玩 RPG,沉迷于其故事情节,现在更加喜欢即时战略。感觉 RPG 现在已经过时了,或者说是小孩子的游戏,因为故事情节比较幼稚,而且玩起来很浪费时间,并且玩通关之后就不想再玩第二遍。而 cs, sc, war3 则不一样,一场战斗就半个小时左右,足够精彩,并且能够享受操作所带来的乐趣。尽管每次都是那几张地图,但是每次都是那么的兴奋。在快节奏的社会里漫长的 RPG 已经很难满足我的需求。网络 RPG 游戏,我还是不喜欢,主要原因还是太过漫长,太浪费时间。至于跑跑卡丁车、跳舞、棋牌之类的休闲游戏,还是蛮不错的,跑跑卡丁车所带来的操作感还是很爽的。 也希望 cloud 早日做出创新的 RPG 游戏,让我再次找回重玩 RPG 的乐趣。
好比那一摄像机摄影,世界在这镜头前不断运动繁衍.好比就是逻辑.摄像机好比就是渲染引擎.所以时间控制是应该归属于这个世界还是取决于摄像机的帧数呢?显然时间是属于时间的.个人认为做出有流畅感的动画关键取决于对于摄像机时间和时间世界之间的精确把握.呵呵,一家之言,高手切莫耻笑.
希望云风以后能多用一些图什么的来配合文字说明
看得不是太明白。
我有一个疑问,如果动画和逻辑分离,让动画去凑逻辑的话,如何让逻辑和表现准确的对齐呢。比如说一刀劈下去,在第7帧打中目标,而动画在第7帧刚好也是刀到了目标的胸口上,这如果用逻辑控制时长,引擎压缩或拉伸动画来完成,怎么保证能匹配上呢?
呵呵不错,不是做游戏开发的,但是觉得这种分析过程很有意思,考虑问题到了这种层次,写代码才会让人比较放心啊
动作控制是老大难问题,之前想过做一个相对通用的可配置动作状态机,一直没时间去实现。 比较理想的接口是上层不用去设置具体播放哪个动画,只要关心我现在处于哪个state,比如站立,跑步,腾空等;或者要进行某个action比如出某一招,挨打等。 至于有哪些state和action,state如何与循环动画对应,state之间的切换动画,同一个action在不同state下呈现为不同的动画,或者state动画的时间比例要和某项数值相关(比如移动速度),这些都是可配置的内容。

Post a comment

非这个主题相关的留言请到:留言本