前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Nebula3中的骨骼动画: Animation子系统

Nebula3中的骨骼动画: Animation子系统

作者头像
逍遥剑客
发布2022-01-11 15:07:18
3830
发布2022-01-11 15:07:18
举报

就像CoreAnimation 中提到的, Nebula2动作系统急需一个全新的设计和编码. 在《龙歌》的开发和另一个针对表情动画的研究中, 我们不得不为这个天生不足的系统加入新的特性. 最后系统勉强可以正常工作了, 但从设计的角度来说, 它的可维性变得很差. 因为从事一个商业项目有很多约束(里程碑, 特性和质量), 这通常是惟一的选择, 最好是让一些事情在里程碑结束前可以工作(就算是内部的实现很杂乱), 以便顺利地完成目标. 至少最后可以确定, 哪些特性需要一个完全的新设计, 和避免错误的实现方法.

把Nebula3当成一个试验台, 《龙歌》完成之前我就开始着手一个新的动作系统. 老系统的主要问题有:

  • 动作低层和高层的特性到处都是, 一些在Nebula2中, 一些在Mangalore中, 还有一些在应用程序里
  • 任意时间点的采样并不真正支持(交叉采样代码需要采样时间以正向增长来改变)
  • 没有混合优先级, 混合权重必须正规化来保证总和为1, 这会产生”有真趣的结果”, 除非应用程序提供了”仔细调谐”的混合权重
  • 局部动作混合(只有角色的一部分骨骼动)一开始并不支持, 后来变相达成的
  • 以不同的采样时间混合2个相同的动作是不可能的
  • 动作剪辑(clip)不能在未来或过去开始
  • … 还有很多小bug和怪事增加了动作系统的复杂性

第一个设计选择是把动作代码分成2个子系统: CoreAnimation 和Animation. CoreAnimation 已经在这里说明过了.

CoreAnimation 主要关心资源的管理, 而高层的Animation系统提供了一些特性来实现复杂的动作混合方案.

刚开始Animation子系统时我考虑的是混合树. 混合树的一片叶子就是采样结点, 它在一个特定时间点采样了一个动作剪辑. 这棵树的结点从输入连接点接收采样数据, 混合(或处理)输入数据到一个单一的输出连接点, 直到根结点, 得到最后的结果. 几个星期的工作和一些接口的修订证明了, 这样的一个系统比老的Nebula2动作系统还要复杂. 我找不到一个简便的方式把”真实世界的情况)输入这棵混合树, 甚至相对简单的混合情况也变得异常复杂.

因此我放弃了混合树, 并开始一种更为直接的优先混合系统, 它基于动作轨道(大致跟Maya’s Trax Editor 差不多). 按照这条新的途径, 所有的事情突然变得条理, 几天后第一个实现就完工了.

新的Animation系统有2个重要的对象类型: AnimJobAnimSequencer.

一个AnimJob 代表一个具有下列属性的单一动作:

  • 开始时间: AnimJob的开始时间, 可以在未来或者过去.
  • 持续时间: AnimJob的持续时间, 不需要跟动作剪辑的长度挂钩, 它也可以是无限的.
  • 混合优先级: AnimSequencer 类实现了优先混合, 高优先级的剪辑支配低优先级的剪辑. 因此具有混合权重1.0的高优先级剪辑会掩盖之前的低优先级剪辑.
  • 混合权重: 最后用于优先混合的权重在淡入淡出时间之内.
  • 淡入淡出时间: 剪辑与当前结果的混合时间.

有了开始时间, 持续时间和混合优先级属性, AnimSequencer 对象安排AnimJobs 到一个2D坐标系统中, 它的水平轴是时间, 垂直轴是混合优先级. 当采样一个指定点时, AnimSequencer首先查找所有经过采样点的动作 job. 然后, 以最低优先级的动作job开始, 每个活动的job会被评估并且结采样果会与之前的混合结果按优先级进行混合.

AnimJob 仅仅是一个基类, 所以可以派生来为混合过程加入定制的功能 (像反向运行学或者一些朝向目标的功能). 现在只有一个特定的子类: PlayClipJob, 它只是简单地采样一个动作剪辑.

新的Animation子系统修正了绝大多数老Nebula2系统的问题:

  • 混合权重的自动正规化由优先级混合代码, 它在实际应用中更加灵活
  • 现在可以评估任意时间点上的动作, 淡入淡出也没有问题
  • 局部的动作混合现在是一个标准特性
  • 动作剪辑现在可以跟自己进行混合
  • 动作job可以在未来或过去开始

总的来说, 新的Animation系统更加简单, 健壮, 易用, 并且易懂.

一些以前证明有用的东西还没有, 或许以后会加入的特性:

  • 动作剪辑的名字映射:
    • 在《龙歌》中, 每个角色有400到600个动作, 大多数是战斗动作的变化(不同的攻击类型, 不同的武器, 有无盾牌, 等等), 但是这些动作实际上只分为几个种类(像攻击, 空闲, 走路…).
    • 如果有映射机制的话会非常方便, 应用程序设置一些变量(像武器类型, 盾牌类型等), 然后一个抽像的”attack”动作名, 经过用户定义的映射规则可以映射到一个特定的“male_twohandedsword_attack1”.
  • 用于定义相关动作之间关系的有限状态机.
    • 这对于自动播放动作变换非常有用. 例如, 一个角色现在没有装备武器, 但是需要播放一个攻击动作, 状态机会决定首先播放一个”拔剑”的动作.(xoyojank: 这里有一个参考)
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2009-05-10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档