Unreal3动画系统概述
发表于2016-06-16
概述
虚幻引擎动画系统为渲染的网格物体和实体添加运动效果。带动画的物体被称为 Skeletal Meshes(骨架网格物体) 。和 Static Meshes(静态网格物体) (它只能通过Matinee进行动画)不同,骨架网格物体使用一组骨骼组成一个 skeleton(骨 架) 。这些骨骼用于驱动物体的运动及在网格物体上物体的放置位置。
动画系统有两个主要部分 – 关键帧动画数据的播放,和动画混合。
管道
动画系统是虚幻引擎传递途径的一部分。首先,处理一般的动画(混合的动画)。然后应用骨骼控制器(比如Inverse Kinematic)。接下来是为骨架设置物理。然后物理子系统处理剩余的物理,最后图形子系统渲染所有的物体。
工作流程
一般,程序员和动画制作人员一同工作来制作所需要的动画内容。动画制作人员将设置一个骨架并根据一个达成一致的惯例来为骨骼添加标签。程序员将基于管道 (类、函数、标记等)把所有的这些结合在一起。
带动画的网格物体
在虚幻引擎中,带动画的网格物体称为 Skeletal Meshes(骨架网格物体) ,因为基于骨骼的骨架动画是用于驱动游戏中物体的动画的主要机制。以前,也有基于顶点的动画。
动画混合
虚幻引擎3使用'混合树'的观念来把多个动画数据源混合到一起。这个方法允许您简单明了地创建一种多个动画混合到一起的方式,并允许您在处理的过程中很容 易地以可预测的方式来添加更多的动画。
混合树概述
这是一个简单的动画混合树:
树是由一些树节点组成。节点主要有两类:
Blend Nodes(混合节点) (圆形) 这些节点有一组子节点,并以某种方式把它们混合到一起。 Data Nodes(数据节点) (方形) 是树的叶子节点,没有子节点但实际上可以生成骨架变换。
在这个例子中,'Directional Blend'节点将会基于actors的速度和方向来把连接到它们的定向动画混合到一起。这将会产生一个定向行走及跑动的动画。然后这些节点插入一个 'Speed-based'中,它将把两个子节点基于Actor的速度混合到一起。最后再将它和Fire混合为'Firing-based Blend'。
基于几种简单在引擎中定义的基本混合模式来创建特定的混合类型是非常容易的。
请查看动画节点页面来查看关于引擎中的默认动画节点的更多信息。
构建混合树
动画树可以使用AnimTree(动画树)编辑器进行构建,它是虚幻编辑器的一部分。您可以使用通用浏览器创建一个新的AnimTree(动画树),然后 双击它,便可以打开AnimTree(动画树)编辑器,并看到一颗新的空的树。
然后您可以在SkeletalMeshComponent的defaultproperties(默认属性)块中告诉它使用您的AnimTree(动画 树)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | defaultproperties { Begin Object Class=SkeletalMeshComponent Name=SkeletalMeshComponent SkeletalMesh=SkeletalMesh 'BigCritter.CritterMesh' AnimSets(0)=AnimSet 'BigCritter.CritterAnims' AnimTreeTemplate=AnimTree 'BigCritter.CritterAnimTree' End Object } |
把AnimTree(动画树)分配给AnimTreeTemplate(动画树模板)是非常重要的,而不是分配给Animations(动画)。当动画播 放开始时,将复制AnimTreeTemplate(动画树模板)引用的AnimTree(动画树),然后把这个实例分配给Animations(动 画),这个实例是游戏播放中真正使用的,因为它包含着实际的状态。
关于AnimTree(动画树)编辑器的更多信息可以从这里获得:动画树编辑器用户指南。
AnimTree(动画树)节点
AnimTree(动画树)节点是建立一个新的AnimTree(动画树)时默认存在的节点。这是您连接Animations(动画)、Blend Nodes(混合节点)及Morph Nodes(顶点变形节点)的地方。您也可以在这里设置一些重要属性。
Blend Nodes(混合节点)和AnimSequences (动画序列)将会产生最终的动画。下一步是应用骨骼控制器。这个工作是以单个步骤完成的,因此骨骼的顺序很重要。让我们设想一下以下的情境:人物使用IK 来移动手臂,使用程序控制器来处理手臂的关节。您将会想先使IK完成动作,然后关节完成动作,这样它可以产生最终的姿势。为了解决这个问题,骨架可以在三 次渲染中进行排列。
ComposePrePassBoneNames 首先组成的骨骼(及它们的子节点)一般是IK Bone 链。 ComposePostPassBoneNames 最后组成的骨骼(及它们的子节点)一般是roll bones(关节)。
混合节点
请参照动画节点页面来获得关于虚幻引擎中的默认动画节点的更多信息。
动画播放
AnimSequence(动画序列),一个AnimSequence(动画序列)是一个单独的动画,它是一个关键帧集合,包含着许多相关的元数据信息,比如notifies(通知)。
AnimSet(动画集),一个AnimSet(动画集)是一个AnimSequences(动画序列)的集合。它们存在于包中,并且可以像材质、网格物体等以同样的方式在通用浏览 器中进行查看。
在一个动画集中的所有AnimSequences(动画系列)必须具有同样数量的轨迹,并且这些轨迹必须指向相同的骨骼。这些应该当您在 AnimSetViewer(动画集)查看器中导入一个PSA文件时为您进行处理。请查看导入动画指南页面来获得关于AnimSetViewer(动画集查看器)和导入动画的更多信息。
请查看动画集编辑器指南页面获得更多的关于AnimSetViewer(动画集查看器)的信息。
骨骼到轨迹的映射
在AnimSet(动画集)中的轨迹是通过名称和骨架网格物体中的骨骼相关联的。这是因为您或许会想在骨骼数量和顺序不同的骨架网格物体上播放同样的动画 集。要想快速地查找存储着一组AnimSetMeshLinkup结构的动画集。这些是特定网格物体上的骨骼和AnimSet(动画集)的轨迹之间的映射 表。
AdditiveAnimation(叠加型动画)
默认情况下,AnimSequences(动画序列)存储着全部的骨架动画。但是它也可以构建并使用叠加型动画。 叠加型动画通过在AnimSet(动画集)编辑器中对两个动画相减来进行构建。然后动画树再使用几个节点把这个叠加型动画添加回去。 Additive Animation(叠加型)动画通过去掉冗余数据从而可以作为一种压缩方式。(比如:放松的走步和瞄准的走步,取出这两种走步,仅保存放松走步和瞄准走 步的不同作为一个附加部分)。尽管是一个进行操作的小技巧,但它可以在很大程度上降低所使用的动画的数量并降低所使用的内存空间。
请查看以下链接来学习关于创建叠加型动画的更多信息:动画集编辑器用户指南#动画序列。
尽管动画集查看器中动画靠它本身便可以达到很好的效果,但是在游戏中它需要被添加到一个基础姿势中,从而看上去更加形象。
您可以通过使用AnimNodeAdditiveBlending节点AnimationNodes#AnimNodeAdditiveBlending或者仅通 过在一个AnimNodeSlot (动画节点元素)AnimationNodes#AnimNodeSlot上根据需求播放它们来添加叠加型动 画。
自从2009年12月份的QA版本开始,Additive(叠加)、 Target(目标)和Base(基础)动画都保持着彼此间的引用。在不同的动画集中移动这些动画并维持这些引用(但不是包)是安全的。当导入一个 Target(目标)或Base(基础)姿势的更新版本时,编辑器将会提醒用户来重新编译相应的叠加型动画。请阅读以下文章来学习关于在 AnimSetViewer(动画集查看器)中导入动画的更多内容导入动画指南。
如果您想更新现有数据并创建这些引用,您可以运行FixAdditiveReferences命令开关。
AnimNodeSequence(动画节点序列)
这是AnimNode(动画节点)的子类,它知道怎样播放存储在AnimSets(动画集)中的关键帧数据。它一般组成您的混合树的叶子节点。
您想要播放的动画序列可以通过在AnimNodeSequence(动画节点序列)中的名称来指定。为了找到那个AnimSequence(动画序列), 它将会查找SkeletalMeshComponent中的整个AnimSets(动画集)数组。通过名称引用动画序列而不是通过指针进行引用的优点是: 它允许您为完全不同的网格物体/动画使用相同的树。当搜索整个AnimSets数组时,它将从末端开始并向前查找,直到找到具有那个名称的 AnimSequence的AnimSet。这允许您在数组中通过添加一个新的具有同样名称动画序列的AnimSet来覆盖特定的序列。
AnimNodeSequence属性
bPlaying (播放) 如果动画当前正在播放时,设置这项。如果当前动画暂停时,不设置这项。 bLooping (循环) 如果动画应该循环并永远播放时设置这项为真。 Rate(速度) 播放速度 bNoNotifies(是否没有通知) 如果设置这项,则不会触发动画通知。 bShowTimeLineSlider(是否显示时间轴滑块) 切换拖动条来控制时间的位置。
AnimGroups(动画组)
当组织很多不同的动画到一起时,便需要在较高的层次上快速地组织和管理这些动画。为了解决这个问题,动画系统使用了AnimGroups(动画组)的概 念。
通过使用AnimGroups,使得同步一系列节点到一起、仅使组中最重要的节点触发通知、及全局地调整所有这些节点的播放速度成为可能。它也可以是这些 选项的组合,不是所有的节点都需要同步。
同步
这个过程在使用一个称为AnimNodeSynch的特殊节点前完成。这个操作自从被集成到AnimGroup系统中时便已经存在。所以我们鼓励移除 AnimNodeSynch。
动画同步背后的原理是可以把不同长度的动画同步到一起。这是非常有用的,比如,对于运动循环。在走动和跑动间的无缝转换。这个主意是为了使动画相对同步。 比如,在整个运动循环中,左脚下降为0%,右脚下降为50%。现在,如果我们保持走步和跑动循环相对地同步到一起,我们便可以根据任务的速度和任何走步循 环的无缝变换来改变每个循环的播放速度。双脚将会被同步。
通知
当在相似的动画间进行变换时,也存在一个处理通知的问题。比如,具有运动动画的脚步。当在不同循环间变换并使用基于权重界线的系统来触发通知时,您可能会 以根本没有触发任何通知的情况告终(或者有时候,可以一次触发几个通知)。我们真正想要的是一个组中最重要的动画来负责触发通知,这也正事 AnimGroups所做的工作。
组可以进行播放速度控制
最终,AnimGroups也允许在组的层次上控制动画的播放速度。注意这是除了每个动画节点速率之外的操作。所以动画节点可以有不同的/各种各样的速 度,而组速度将在它们独立的播放速率之上来缩放那个组中所有动画节点的速率。
设置
为了创建一个组,请选择AnimTree节点(混合树的根节点)。展开AnimGroups,并添加一个新项,在"GroupName(组名)"属性中为 您的组输入您想使用的名称。RateScale属性是用于缩放这个组的全局播放速度。
然后,选择您想添加到这个组中的AnimNodeSequence节点。展开它的Group部分,您将会看到以下属性:
bForceAlwaysSlave 节点将会被同步,但是永远不会被选择为主要节点。 bSynchronize 默认为真,节点将会被同步。如果您不想同步这个节点,请不要选中此项。 SynchGroupName 这个节点所属于的组的名称。设置它为和您在AnimTree AnimGroups 数组中创建的组名称一样的组。 SynchPosOffset 如果所创建动画不是和其它动画(左脚、反向的右脚)进行相对地同步,那么通过偏移动画来使它匹配是可能的。Offset (偏移)是一个相对位置,从0.f到1.f。
内部实现
分组系统,当所有的节点被实时计算后,在第二次中它将会强制更新组中所有的节点。所以在混合树中的所有节点都具有最新的权重。然后每个组将会寻找两个主要 节点。一个用于同步,另一个用于通知。要使用2个主要节点的原因是不是所有的节点都需要被同步,并且也不是所有的节点都需要触发通知。所以在每个种类中的 主要节点都是最相关的节点(在树中具有最高权重的节点,可以活着被同步活着触发通知)。一旦选择了主要节点,那么所有的组节点都是补充资料,需要同步的节 点是,需要触发通知的节点也是。
在AnimTree中有几个有用的脚本函数用于从脚本代码中控制组。添加/删除节点、控制同步位置、播放速度缩放等。
根骨骼运动
请参照根骨骼运动页面。
骨骼控制器
当动画已经被提取出来并混合到一起后,便可以应用骨骼控制器,比如IK(逆向运动学)。请查看SkeletalControllers(骨架控制器)页面 来获得关于这个步骤以及您可以使用的节点类型的更多信息使用骨架控制器。
物理动画
关于结合物理和动画的更多信息,请参照物理动画页面。
有用的控制台命令
show bones - 显示用于渲染骨架网格物体的骨骼的位置。