发布时间:2023-12-17 09:30
一、Animation
Unity的动画特性包括可重定向动画,在运行时控制动画权重,动画播放时的事件调用,复杂的状态机Hierarchies和动画间的过渡、面部动画的blendshape等等。
1.动画系统概述
Unity有一个复杂而丰富的动画系统(有时被称为Mecanim).它提供了:
·简单的工作流以及Unity所有元素的动画设置,包括对象,角色和属性。
·支持在unity中导入Animation clips以及创建Animation
·Humanoid animation retargeting--将动画从一个角色模型应用到另一个角色模型的能力
·简单的工作流用于调整Animation clips
·可以方便的预览Animation clips,以及动画间的过渡和交互。这允许动画师更加独立于程序员工作,可以在游戏运行代码前,预览和创建动画原型。
·使用可视化编程工具管理动画之间复杂的交互
·用不同的逻辑驱动不同的动画
·Layers以及masking特性
(1).动画工作流程
Unity的动画系统是基于Animation Clips的概念,它包含某些对象如何随着时间改变位置、旋转或其他属性的信息。每一个clip可以被认为是单个线性记录。来自外部源的Animation Clips是由艺术家或动画师使用第三方工具,如Autodesk 3dsMax,Autodesk Maya,或者来自动作捕捉工作室以及其他来源。
然后将Animator Clips组织成一个类似结构的流程图系统,称为Animator Controller。Animator Controller充当“状态机”,用于跟踪当前正在播放的剪辑,以及动画何时应该更改或混合在一起。
一个非常简单的Animator Controller可能只包含一个或两个Animator clips,例如控制一个向上旋转和跳跃,或者在正确的时间激活一个打开和关闭门的动画。一个更高级的动画可能包含几十个Humanoid动画,用于所有主要角色的动作,并且可以同时在多个clips之间进行混合,以提供流畅的动作,当玩家在场景中移动时。
Unity的动画系统还具有许多用于处理Humanoid动画的特殊功能,让你能够从任何来源(例如:动画捕捉,Asset Store或者其他一些第三方动画库)将Humanoid动画重新定位到你自己的角色模型,以及调整肌肉定义。这些特殊的特性是由Unity的Avatar系统所支持的,它将Humanoid角色映射到一个通用的内部格式。
每一个Animation Clips,Animator Controller以及Avatar都通过Animator组件放在一个游戏对象上。该组件引用了Animator Controller,并且(如果需要的话)可以引用这个模型的Avatar。反过来,Animator Controller包含了对它所使用的Animation Clips的引用。
上面的图显示了以下内容:
1.Animation clips是从外部源导入或在Unity中创建。在这个例子中,他们是导入动作捕捉的Humanoid动画。
2.Animation clips被放置并安排在一个Animation Controller中.这显示在Animator窗口的Animator Controller视图中。状态(可以表示动画或嵌套的子状态机)显示为由线连接的节点。Animator Controller作为项目窗口中的一种asset存在。
3.被装配的角色模型(在本例中,宇航员"Astrella")具有特定的骨骼结构,这些骨骼被映射到Unity的通用Avatar格式。该映射作为导入的角色模型的一部分存储为Avatar asset,并显示在项目窗口中。
4.如果角色模型有动画,它会有一个Animator组件。在上面显示的Inspector视图中,你可以看到Animator组件既有Animator Controller也有指定的Avatar.animator。动画师一起使用它们来为模型制作动画。Avatar只在humanoid角色动画中是必要的,对于其他类型的动画,只需要animator controller.
(2).传统动画系统
虽然建议大多数情况下使用Mecanim,但unity保留了其在Unity4之前存在的传统动画。使用Unity4之前创建的旧内容时可能需要使用。
2.Animation Clips
Animation是Unity动画系统的核心元素之一。Unity支持从外部源导入动画,并提供使用Animation窗口在编辑器中从头开始创建Animation clips的功能。
(1).外部来源的动画
从外部来源导入的Animation clips可以包括:
·在一个动画捕捉工作室拍摄的Humanoid动画
·艺术家在外部3D应用程序(例如Autodesk 3dsMax、Autodesk Maya)中从头开始创建动画。
·来自3rd-party库的动画集(例如:来自Unity的asset store)
·从单个导入的timeline上剪切和切片多个剪辑
(2).在unity中创建和编辑动画
Unity的动画窗口还允许你创建和编辑Animation clips.这些clips可以编辑:
·GameObject的position,rotation以及scale
·组件的属性,例如:材质的颜色,光的强度,以及声音的音量
·你自己脚本中的属性,包括float,int,enum,vector以及bool变量
·在你自己的脚本中调用函数的时间
3.外部来源的动画
来自外部源的动画以与常规3D文件相同的方式导入到unity中。这些文件,无论是通用的FBX文件,还是来自3D软件的原生格式,如 Autodesk Maya,Cinema 4D,Autodesk 3ds Max,都可以包含动画数据,以线性记录对象移动的形式。
在某些情况下,有动画的对象(例如,角色)和与之相关的动画可以出现在同一文件中。在其他情况下,动画可以存在于一个单独的文件夹中,不与相关联的模型放在一起。
动画有可能特定于特定模型,并且不能在其他模型上重复使用。例如,游戏中的巨型章鱼末端boss可能具有独特的肢体和骨骼排列,以及它自己的一组动画。
在其他情况下,你可能拥有一个动画库,可用于场景中的各种不同模型。例如,许多不同的humanoid角色可能都使用相同的走路和跑步动画。在这些情况下,为了预览它们,在动画文件中使用简单的占位符模型是很常见的。或者,即使它们根本没有几何体,也可以使用动画文件,只有动画数据。
导入多个动画时,动画可以作为项目文件夹中的单独文件存在,或者你可以从单个FBX文件中提取多个动画片段(如果从Motion构建器导出,或者使用Autodesk Maya插件/脚本、Autodesk 3dsMax或其他3D软件包).如果你的文件包含多个排列在一个时间轴上的单独动画时,你可能需要这样做。例如,一个长时间的动作捕捉的timeline可能包含一些不同的跳跃动作的动画,你可能希望将其中的某些部分剪切掉以用作单个clips并丢弃其余部分。Unity提供了动画剪辑工具,当在一个时间轴中导入所有动画时,通过允许你为每个剪辑选择帧范围实现此目的。
(1)导入动画文件
在Unity中使用任何动画之前,必须先将其导入项目中。Unity可以导入原生Autodesk Maya(.mb或.ma),Autodesk 3dsMax(.max)和Cinema 4D(.c4d)文件,以及可从大多数动画包导出的通用FBX文件。
(2)从导入的动画文件中查看和复制数据
你可以在Animation窗口中查看导入的animation clips的关键帧和曲线。有时候,如果这些导入的剪辑有很多带有大量关键帧的骨骼,那么信息量可能看起来就会非常复杂。为了简化视图,选择你要检查的特定骨骼。然后Animation窗口只显示这些骨骼的关键帧和曲线。
在查看导入的动画关键帧时,动画窗口提供动画数据的只读视图。要编辑此数据,请在Unity中创建一个新的空Animation Clip,然后从导入的Animation Clip中选择,复制和粘贴Animation data到新的可写Animation Clip中。
4.Humanoid Avatars
Unity的角色动画系统有专门的功能来处理humanoid角色。因为humanoid角色在游戏中是非常常见的,所以Unity提供了一个专门的工作流,以及一个用于humanoid animations的扩展工具集。
Avatar系统是Unity用于识别特定动画模型在布局中是humanoid,模型的哪些部分对应于腿,手臂,头部和身体。
由于不同的humanoid角色之间的骨骼结构相似,可以将动画从一个humanoid角色映射到另一个humanoid角色,从而允许重定向和反向运动学(IK).
5.Animation窗口指导
Unity中的Animation窗口允许你直接在unity中创建和修改Animation Clips。它旨在作为外部3D动画程序的强大而直接的替代品。除了移动动画之外,编辑器还允许你为材质和组件的变量设置动画,并使用Animation Event(沿时间轴在指定点调用的函数)扩充animation clips。
(1).Animation窗口和Timeline窗口的区别
TimeLine窗口
TimeLine窗口允许你创建电影内容,游戏播放序列,音频序列和复杂的粒子效果。你可以在同一序列中为许多不同的游戏对象制作动画,例如剪切场景或角色与场景交互的脚本序列。在Timeline窗口中,你可以有多重类型的轨道,每个轨道可以包含多个可以移动,修剪和混合的剪辑。它对于创建需要许多不同的游戏对象一起编排的复杂动画序列非常有用。
TimeLine窗口比Animation窗口更新。它被添加到2017.1版本的Unity中,并取代了Animation窗口的一些功能。
Animation窗口
Animation窗口允许你创建单独的animation clips,以及查看导入的animation clips。animation clips存储单个GameObject或单个 hierarchy GameObjects的动画。Animation窗口对于在你的游戏中制作离散的物品是很有用的,比如一个摆动的钟摆,一个滑动门,或者一个旋转的硬币。动画窗口一次只能显示一个动画剪辑。
在4.0版本中,Animation窗口被添加到Unity中。Animation窗口是一个比Timeline窗口更古老的特性。它提供了一种创建Animation clips和为各个GameObject设置动画的简单方法,你在Animation窗口中创建的clips,可以使用Animator Controller进行组合和混合。但是,涉及许多不同游戏对象的更复杂的序列,你应该使用Timeline窗口。
Animation窗口有一个“timeline”作为它的用户界面的一部分(水平栏上标有时间描绘),但是这与Timeline窗口是分开的。
6.使用Animation视图
Animation视图用于预览和编辑Unity中的GameObject的Animation clips.通过
Window -> Animation可以打开Animation视图。
(1).查看GameObject上的动画
Animation窗口与Hierarchy窗口,Project窗口,Scene视图和Inspector窗口衔接。像Inspector一样,Animation窗口显示当前选择的GameObject或Animation Clip Asset的动画的时间轴和关键帧。你可以使用Hierarchy窗口或者Scene视图选择GameObject,也可以通过Project窗口选择Animation Clip Asset.
注意:Animation视图是独立的,但看起来跟Timeline窗口很相似。
(2).动画属性列表
在下图中,Animation视图(左边)显示了当前选中的GameObject以及它的子GameObject所使用的动画,如果它们被该动画控制的话。Scene视图和Hierarchy视图在右侧,演示了Animation视图怎么显示当前选中的GameObject上的附加动画。
在动画视图的左侧是一个动画属性列表,在一个尚未录制动画的新创建的clip中,这个列表是空的。
当你开始为clips中的各种属性做动画时,动画属性将出现在这里。如果动画控制了多个子对象,那么该列表还将包含每个子对象的动画属性的分层子列表。在上面的例子中,机器人手臂的GameObject Hierarchy的各个部分都在同一个Animation clip中做动画。当像这样在单个clips中为一个GameObject的Hierarchy做动画时,请确保在Hierarchy的根GameObject上创建动画。
可以折叠和展开每个属性,以显示在每个关键帧记录的确切值。如果回放头(白线)位于关键帧之间,则值字段显示插值值。你可以直接编辑这些字段。如果当回放头位于关键帧之上时进行了更改,则修改关键帧的值。如果当回放头在关键帧之间(因此显示的值是插值值)时发生改变,那么在那个点将使用输入的新值创建一个关键帧。
(3).动画时间轴
在动画视图的右侧是当前clip的timeline。这个timeline展示了每个动画属性的关键帧。timeline视图有两种模式,Dopesheet和curve。要在这些模式切换,单击动态属性列表区域底部的Dopesheet或Curve。
它们提供了动画时间轴和关键帧数据的两个备用视图。
Dopesheet时间轴模式:
Dopesheet模式提供了一个更紧凑的视图,允许你在单个水平轨道中查看每个属性的关键帧序列。这允许你查看多个属性或GameObjects的关键帧时序的简单概述。
Curves时间轴模式
Curves模式显示一个可调整大小的图形,其中包含了每个动画属性的值随时间变化的视图。所有选中的属性都显示在同一个图形视图中。通过此模式,你可以很好地控制查看和编辑值,以及如何在两者之间进行插值。
让你的选择适合窗口
当使用曲线模式来查看动画时,重要的是要明白有时候每个属性的不同范围会有很大的差异。例如:考虑一个用于旋转弹跳立方体的简单Animation clip。弹跳Y位置值可以在0到2的范围内变化(意味着在动画期间立方体弹跳2个单位高);但是旋转值从0到360(表示旋转度)。当同时查看这两条曲线时,位置值的动画曲线将会非常难以辨认,因为视图将会缩小到适合窗口内0-360范围的旋转值。
按键盘上的F可将视图缩放到当前选定的关键帧。这对于在动画时间轴的一部分上聚焦和重新缩放窗口以便于编辑非常有用
单击列表中的各个属性,然后按键盘上的F以自动重新缩放视图以适合该值的范围,以自动重新缩放视图以适应该属性值的范围。你还可以使用视图滚动条滑块每端的拖动手柄调整Curves窗口的缩放。在下图中,动画窗口被放大以查看弹跳Y位置动画。黄色旋转曲线的起点仍然可见,但现在已经远远超出了视图的顶部。
按下键盘上的A键来适应和重新缩放窗口以显示clip中的所有关键帧,无论选择哪个。如果要在保留当前选择的同时查看整个时间轴,这非常有用
回放和帧导航控件
要控制Animation Clip的回放,请使用Animation视图左上角的回放控件。
从左到右,这些控件是:
·预览模式(打开/关闭)
·记录模式(切换打开/关闭),注意:如果记录模式打开,预览模式总是打开的
·移动播放头到clip的开始
·移动播放头到前一个关键帧
·播放动画
·移动播放头到下一个关键帧
·移动播放头到clip的末尾
你还可以使用键盘快捷键控制播放头
·按逗号 (,) 进入前一帧
·按句号 (.) 转到下一帧
·按住Alt键并按下逗号 (,) 进入前一个关键帧
·按住Alt键并按下句号 (.) 进入下一个关键帧
锁定窗口
你可以锁定Animation编辑器窗口,这样它就不会自动切换以反映在Hierarchy或Scene中当前选中的GameObject.如果你想专注于某个特定GameObject的动画,并且仍然能够选择和操作场景中的其他游戏对象,锁定窗口是很有用的。
7.创建一个新的动画clip
要在Unity中为GameObject设置动画,需要在GameObjects上附加Animator组件。此Animator组件必须引用Animator Controller,而Animator Controller又包含对一个或多个Animation Clips的引用。
使用Animation视图开始在Unity中设置GameObject动画时,将自动为你创建,附加和设置所有这些项目。
为选定的GameObject创建新的Animation clip,并确保Animation窗口可见。
如果GameObject尚未分配任何动画clip,你将会在Animation窗口时间轴的中心看到“Create”按钮。点击Create按钮。然后系统会提示你将新的空动画clip保存到Assets文件夹中。
一旦你保存了这个空的Animation clips,很多事情会自动发生:
·将创建一个新的Animation Controller asset
·正在创建的新clip将作为默认状态添加到Animator Controller中
·Animator组件将被添加到正在做动画的GameObject中
·为Animator组件分配新的Animator Controller
这个自动序列的结果是为你设置了动画系统的所有必须元素,现在你可以为对象设置动画了。
(1).添加另一个Animation Clip
如果GameObject已经分配了一个或多个Animation Clips,"Create"按钮将不可见。相反,其中一个clip将在Animation窗口可见。你可以通过使用Animation窗口左上方的菜单,在播放控件下切换窗口中可见的Animation clip.
如果你想在一个已经有动画的对象上创建一个新的Animation Clip,你可以从这个菜单中选择“Create New Clip”。同样,你将被提示保存新的Animation clip,然后才能使用它。
(2).Animation clip的组合
虽然以上步骤会自动设置相关的组件和引用,但是了解哪些部分必须连接在一起是很有用的。
·GameObject必须具有Animator组件
·Animator组件必须分配Animator Controller asset
·Animator Controller asset必须分配一个或多个Animation clip
下面的图表显示了如何分配这些片段,从Animation窗口创建新的Animation clip开始:
在下图中,你可以看到被选择的GameObject(“Cube”)尚未有动画。我们只有一个没有Animator组件的简单的立方体。Animation窗口,Hierarchy窗口,Project窗口以及Inspector窗口并排排列,以保持清晰。
在Animation视图中按下Create按钮,就会创建一个新的Animation clip。Unity会要求选择名称和位置来保存这个新的Animation clip.Unity还创建了一个与所选GameObject同名的Animator Controller asset,向GameObject添加了Animator组件,并适当的将asset连接起来。
在上面的新视图中,你可以看到
·动画窗口(左上角)现在显示了一个带有白色播放头线的时间线,可以记录新的关键帧。clip的名称在clip菜单中可见,就在回放控件的下面。
·Inspector(中心)显示了Cube GameObject现在添加了Animator组件,组件的Controller字段显示分配了名字为Cube的Animator Controller asset
·Project窗口(右下)显示已经创建了两个新资产-一个名为"Cube"的Animator Controller asset和一个名为"Cube Animation Cilp"的Animation Clip资产。
·Animator窗口(左下)显示了Animator Controller控制器的内容-可以看到"Cube Animation Clip"已经添加到控制器中,它是橙色表示的默认状态。添加到Controller的后续clip将使用灰色,标明它们不是默认状态。
8.设置GameObject动画
一旦你保存了新的Animation clip Asset,你就可以开始向clip添加关键帧了。
在动画窗口中有两种不同的方法可以用来为GameObject做动画:记录模式和预览模式。
记录模式(也称为自动按键模式):
在录制模式下,当你移动,旋转或修改动画游戏对象上的任何可动画属性时,Unity会在回放头自动创建关键帧。按下带有红色圆圈的按钮,即可进入录制模式。在记录模式下,动画窗口的时间线是红色的。
预览模式:
在预览模式下,修改需要动画的GameObject不会自动创建关键帧。每次将GameObject修改为所需的新状态(例如,移动或旋转它)时,必须手动创建关键帧(如下所示)。按下预览按钮以启用预览模式。在预览模式下,动画窗口的时间线是蓝色的。
注意:在录制模式下,预览按钮也是活动的,因为你正在预览现有的动画并同时记录新的关键帧。
(1).记录关键帧
要开始记录所选GameObject的关键帧,单击Animation Record按钮。这将进入Animation Record Mode,对GameObject的更改将被记录到Animation Clip中。
一旦进入录制模式,你可以通过将白色回放头设置为动画time line中所需的时间来创建关键帧,然后将GameObject修改为你希望它处于的状态。
你对GameObject所做的更改将被记录为Animation窗口中的白线(回放头)显示的当前时刻的关键帧。
对可动画属性的任何修改(如其位置或旋转)将导致该属性的关键帧出现在动画窗口中。
单击或拖动时间线条可移动回放头,并显示回放头当前时间的动画状态。
在下面的截图中,你可以看到动画窗口在录制模式。时间线条被着色为红色,表示记录模式,动画属性在Inspector中显示为红色背景。
你可以通过再次单击Record按钮随时停止记录模式。当你停止记录模式,动画窗口切换到预览模式,这样你仍然可以根据动画time line看到游戏对象的当前位置。
你可以在动画记录模式下通过操作GameObject的任何属性来为它设置动画。移动,旋转或缩放游戏对象在Animation clip中为这些属性添加相应的关键帧。在记录模式下,在GameObject的Inspector中直接调整值也会添加关键帧。这适用于inspector中的任何可动画属性,包括数值,复选框,颜色和大多数其他值。
当前动画的GameObject属性将显示在Animation窗口的左侧。没有动画效果的属性不会显示在这个窗口中。你动画的任何新属性,包括子对象上的属性,一旦开始动画它们,就会添加到属性列表区域。
Transform属性的特殊之处在于x,y和z属性时链接在一起的,因此同时添加这三个属性的曲线。
你还可以通过单击add Property按钮向当前GameObject(游戏物体)(及其子对象)添加可动画属性。单击此按钮将显示GameObject可动画属性的弹出列表。这些属性和inpector中列出的属性相对应。
在预览模式或录制模式下,白色垂直线显示当前预览Animation Clip的哪个帧.Inspector和Scene视图在Animation clip的那一帧显示GameObject.该帧的动画属性值也显示在属性名称右侧的列中。
在动画模式下,白色垂直线显示当前预览的帧。
(2).时间轴
你可以单击Animation窗口time line上的任意位置,将回放头移动到该帧,并在动画剪辑中预览或修改该帧。时间轴中的数字显示为秒和帧,所以1:30表示1秒和30帧。
注意,Animation窗口中的time line bar共享相同的名称,但在Timeline窗口中是分开的。
注意:在预览模式下time line显示为蓝色,在记录模式下显为红色。
(3).在预览模式下创建关键帧
除了使用记录模式在修改GameObject时自动创建关键帧外,你还可以在Preview模式通过修改GameObject上的属性,然后手动地选择为该属性创建关键帧。
在预览模式下,有动画的属性在Inspector窗口中显示为蓝色。当你看到这个蓝色色调时,这意味着这些值是由animation clip的关键帧驱动的,当前animation clip正在动画窗口中预览。
如果你在预览时修改了这些蓝色属性中的任何一个(比如旋转一个带有旋转属性动画的GameObject,如上图所示),GameObject现在就会处于修改后的动画状态。这inspector字段的颜色更改为粉红色来表示。因为你没有处于记录模式,所以你的修改还没有保存为关键帧。
例如,在下面的截图中,旋转属性被修改为Y值为-90。此修改尚未保存为animation clip中的关键帧。
在此修改状态下,必须手动创建关键帧以“保存”此修改。如果你移动回放头,或者从动画游戏对象中切换你的选择,你将失去修改。
(4).手动创建关键帧
当你在预览模式下修改了GameObject时,有三种方法可以手动创建关键帧。
你可以通过右键单击你修改过的属性的属性标签来添加关键帧,这样你就可以为这个属性添加关键帧,或者为所有的动画属性添加关键帧。
添加关键帧后,新的关键帧将在animator窗口可见作为一个菱形符号(在下面的截图中用红色表示),属性字段重新变回蓝色,表明你的修改被保存为一个关键帧,并且你现在正在预览一个由动画关键帧驱动的值。
你也可以通过点击动画窗口中的add keyframe按钮来添加关键帧。
或者你可以使用热键K或Shift-K来添加一个关键帧(或多个关键帧),如下所述:
热键
·K-所有动画的关键帧。在animation窗口中回放头当前位置为所有动画属性添加一个关键帧。
·Shift-K-所有修改的关键帧。仅为那些在animation窗口中回放头的当前位置修改过的动画属性添加关键帧。
10.使用动画曲线
(1).属性列表
在Animation Clip中,任何可动画属性都可以有动画曲线,这意味着Animation Clip可以控制该属性随时间变化。在Animation视图(左边)的属性列表区域中,列出了所有当前的动画属性。在Dopesheet模式下的动画视图中,每个属性的动画值只显示为线性轨迹,但是在Curves模式下,你可以看到属性的变化值显示为图形上的线。无论你使用哪种模式来查看,曲线都是存在的。只有当关键帧出现时,Dopesheet模式才会提供数据的简化视图。
在Curves模式中,动画曲线有彩色的曲线指示器,每种颜色代表属性列表中当前选中属性的值。
(2).理解Curves,Keys,Keyframes
Animation Curve有多个keys,这些keys是曲线经过的控制点。这些在曲线编辑器中可视化为曲线上的小菱形。一个帧中若有一条或多条曲线有一个key,则这一帧被称为keyframe.
如果属性在当前预览帧中有一个key,则曲线指示器将具有菱形形状,属性列表也将在值旁边具有菱形形状。
Curve编辑器将只显示所选属性的曲线。如果在属性列表中选择了多个属性,则曲线将显示在一起。
(3).添加和移动关键帧
可以通过单击keyframe按钮在当前预览帧中添加关键帧。这将为所有当前选中的曲线添加一个关键帧。或者你可以通过双击新keyframe所在的曲线,将关键帧添加到任意给定帧的单个曲线中。还可以通过右键单击关键帧所在曲线,并从上下文菜单中选择Add Keyframe来添加关键帧。一旦放置,关键帧可以用鼠标拖动。也可以同时选择多个关键帧来拖动。关键帧可以通过选择他们并按下Delete来删除,或者右键单击它们并从上下文菜单中选择Delete keyframe.
(4).支持动画的属性
Animation视图不仅可用于为GameObject的position,rotation和scale设置动画。任何Component和Material的属性都可以被设置动画–甚至是自己的脚本组件的公共变量。制作具有复杂视觉效果和行为的动画,只需为相关属性添加动画曲线即可。
动画系统支持一下类型的属性:
·Float
·Color
·Vector2
·Vector3
·Vector4
·Quaternion
·Boolean
不支持Arrays,除了上面列出的structs或objects,其他的的struct或对象也不受支持。
对于布尔属性,0的值为False,而其他值为True.
下面是一些Animation View可以用来做的事情的例子:
·为光线的颜色(Color)和强度(Intensity)做动画效果
·为循环Audio Source的Pitch和Volume设置动画,模拟生活中吹的风,引擎发动,或流动的水的效果,同时保持sound assets的规模最小。
·为Material的Texture Offset设置动画,以模拟移动的带子或轨道,流动的水,或特殊效果。
·为多个Ellipsoid Particle Emitters的Emit state和Velocities做动画效果,以创造壮观的烟花或喷泉显示
·为自己的组件脚本的变量设置动画,以使不同时间有不同行为。
当使用Animation Curves开控制游戏逻辑时,请注意动画在Unity中的回放和采样方式。
(5).旋转插值类型
在Unity内部旋转表示为四元数。四元数由x,y,z,w组成,这些值一般不需要手动修改,除非你知道他们的确切含义。一般旋转通常使用欧拉角来操作,欧拉角用x,y,z来表示围绕着三个轴的旋转。
在两个旋转之间进行插值时,可以对四元数或欧拉角进行插值。Animation视图允许你选择在动画转换旋转时使用哪种插值形式。然而无论采用哪种插值形式,旋转总是以欧拉角值的形式出现。
(6).四元数插值
四元数插值总是在两个旋转之间的最短路径上产生平滑的旋转变化。这避免了万向节锁等问题。然而四元数插值不能表示大于180度的旋转,因为它总是寻求最短路径。(你可以通过在球面上选取两点来描绘这一点–它们之间的最短直线永远不会超过球面的一半)。
如果你使用四元数插值,将数值旋转的值间隔超过180度,那么在动画窗口中绘制的曲线看起来仍然会覆盖超过180度的范围,但是物体的实际旋转会旋转最短路径。
当使用四元数插值进行旋转时,改变x,y或者z曲线的键或切线也可能改变其他两天曲线的值,因为这三条曲线都是从内部四元数表示中创建的。当使用四元数插值时,key总是连接在一起的,因此在特定时间为三条曲线中的一条(x,y或z)创建一个key,同时也为其他两天曲线创建一个key.
(7).欧拉角插值
欧拉角插值是大多数人都熟悉的。欧拉角可以表示任意大的旋转,而x,y,z曲线时相互独立的。欧拉角插值在同时围绕多个轴旋转时,可能受到万向锁等人为因素的影响,但对于一次围绕一个轴的简单旋转来说,这种方法是直观的。当使用欧拉角插值时,Unity内部将曲线烘焙成内部使用的四元数表示形式。这与从外部程序将动画导入Unity时会发生的情况类似。注意,这种曲线烘焙可能会在这个过程中添加额外的键,并且在子帧级别上与常切类型的切线可能不是完全精确的。
11.编辑曲线
Unity Editor中有几个不同的功能和窗口,它们使用Curves来显示和编辑数据。尽管有一些例外情况,但你可以用来查看和操纵曲线的方法在所有这些方面基本相同。
·Animation窗口使用曲线在Animation Clip中随时间显示和编辑动画属性的值。
·Script组件可以具有Animation Curve类型的成员变量可用于各种事物。单击Inspector将打开曲线编辑器。
·Audio Source组件使用曲线来控制roll-off和其他属性,最为到Audio Source的距离的函数。
·Particle System 使用曲线随时间改变离子属性
虽然这些控件有细微的差别,但曲线可以在所有控件中以完全相同的方式进行编辑。
(1).在曲线上添加和移动keys
通过双击应放置key的曲线上的点,可以将key添加到曲线上。还可以通过右键单击曲线并从上下文菜单中选择add key来添加键。
一旦放置,key可以用鼠标拖动:
·单击一个key来选中它,然后用鼠标拖动选中的key
·要想在拖动网格的同时对齐key,请拖动时,Mac平台按住Command键,Windows平台按住Control键。
也可以同时选择多个key:
·单击key时按住Shift键可以同时选择多个键。
·若要取消选定的key,可以再按住Shift键的同时再次单击它
·若要选择矩形区域内的所有key,单击空点并拖动以形成矩形选择。
·矩形选择还可以通过按住Shift键添加到现有的选中的key中。
key可以通过选择它们并按下Delete来删除,或者右键单击它们并从上下文菜单中选择Delete键。
(2).编辑Keys
直接在曲线编辑器中编辑key是Unity5.1中的一个新特性。使用Enter/Return或者上下文菜单开始编辑选中的key,Tab可以在字段之间切换,Enter/Return用于提交,Escape取消编辑。
(3).曲线导航视图
使用Animation视图时,你可以轻松的放大你想要使用的曲线的细节,或者缩小以获得完整的图片。
你可以按F键来显示选中frame或者选中key的曲线。
(4).缩放
你可以使用鼠标的滚动轮,使用触控板的缩放功能,或者用鼠标右键拖动按住Alt键来缩放视图。
你只能放大水平轴或垂直轴:
·在Mac按住Command或者Windows按住Control键来进行水平缩放。
·缩放的同时按住Shift键垂直缩放。
此外,你还可以拖动滚动条的端点,以收缩或扩展曲线视图中的显示的区域。
(5).平移
你可以用鼠标中键或者用鼠标左键拖动的同时按住Alt键来平移曲线视图。
(6).编辑切线
一个key有两个切线-一个在左边用于表示进来的斜率,一个在右边用于表示出去的斜率。切线控制key之间的曲线的形状。你可以从许多不同的切线类型中进行选择,以控制曲线如何离开一个key并到达下一个key。右键单击一个键以选择该键的切线类型。
要使有动画的值在传递key时平滑地改变,左切线和右切线必须是共线的。以下切线类型可确保平滑度:
·Clamped Auto:这是默认的切线模式。切线自动设置为使曲线平滑的经过key.当编辑key的位置或时间时,切线会调整以防止曲线"超过"目标值。如果在Clamped Anto模式,你手动的调整key的切线,它会切换到Free Smooth模式。在下面的例子中,当key被移动时,切线会自动进入一个斜率并水平移动
·Auto:这是一个遗留的切线模式,并且仍然是一个向后兼容旧项目的选项。除非你有特定的理由使用此模式,否则请使用默认的Clamp Auto模式。当将key设置为该模式时,会自动设置切线,使曲线平滑的经过key.但是与Clamped Auto模式有两个区别:
1.当key的位置或时间被编辑时,切线不会自动调整,它们只在最初将key设置为此模式时,进行调整
2.当unity计算切线时,它没有考虑到避免"超过"目标值的key.
·Free Smooth:拖动切线手柄可自由设置切线。它们被锁定为共线以确保平滑。
·Flat:切线设置为水平方向(这是Free Smooth的特殊情况)
有时你可能不希望曲线在通过一个key时是平滑的。要在曲线上产生明显的变化,请选择Broken tangent模式
当使用broken tangents时,可以分别设置左切线和右切线。每个左右切线都可以设置为以下类型之一:
·Broken-Free:拖动切线手柄可自由设置切线。
·Broken-Linear:相切点指向相邻的key.要做一条直线线段,把两端的切线都设为直线。在下面的示例中,所有的key都被设置为断线,以实现从key到key的直线。
·Broken-Constant:曲线在两个key之间保持恒定值。左键的值决定了曲线段的值。
12.在Dopesheet模式下的key操作
Box Selection用于在Dopesheet模式下查看Animation窗口时选择多个键。这允许你一次选择和操作几个键。
以下操作允许你选择多个键:
·按住Shift+click可将某个key添加到你的选择中
·用鼠标拖动一个矩形来选择一组key
·按住Shift并拖动一个矩形来添加或删除当前选择的一组键
当向选择添加key时,框选择句柄会出现在所选键的任意一侧。如果向选择添加或删除更多key,句柄将自动调整其位置和大小,以包含所有当前选中的key.
使用框选择句柄来移动,缩放和编辑所选的key(参见下面的Ripple编辑)
(1).移动选择的key
单击框选择句柄内的任意位置,拖动选中的键并移动它们。你不需要直接点击一个key来做这个,你可以通过单击框选择句柄内的空白空间来拖动。
当你拖动时,第一个和最后一个key的时间会显示在时间轴栏下,以帮助你把key放在你想要的位置。当将选择的key拖动到左边时,任何以负时间结束的key(即时间轴上0标记的左边)都会在释放鼠标按钮时被删除。
(2).缩放选择key
当你选择了多个key,你可以缩放所选择的key,或者把它们分开很长一段时间(使所选择的动画变慢),或者把他们靠得更近以占用更短的时间(使所选择的动画变快)。要缩放选中的key,单击并按住选中键左右两侧的蓝色框选择手柄,水平拖动。
当你缩放时,第一个和最后一个key的时间将显示在时间轴栏下,以帮助你缩放键到所需的位置。当将选择的key缩减到更短的时间时,有些key可能会以相同的帧结束。如果发生这种情况,当你释放鼠标按钮时,占用相同frame的额外key将被丢弃,并且只保留最后一个key.
(3).Ripple 编辑
Ripple编辑是一种移动和缩放选定key的方法。此方法还会影响与你正在操作的key在同一时间轴上的非选中key.该名称是指让其他内容自动沿time line移动,以适应你添加、扩展或缩小的内容。编辑的效果会在整个时间轴上产生“ripple效应”
按住R键同时拖动选择框内来执行一个Ripple Move。这样做的效果是“推”任何未选中的key,加上你选择的key和那些key之间的原始空间,当你沿着时间轴拖动所选key时,就会在选择key的左边或右边。
按住R键同时拖动方框选择手柄来执行Ripple Scale.对时间轴中其他未选中的key的影响与Ripple Move完全相同–当你缩放到框选择的左边或右边时,他们被推倒左边或右边。
13.在Curves模式下的key操作
方框选择用于在曲线模式下查看Animation窗口时选择多个key.这允许你一次选择和操作几个key.
以下操作允许你选择多个key:
·按住Shift + 单击可将单个键添加到你的选择中
·用鼠标拖动一个矩形来选择一组key
·按住Shift并拖动一个矩形来添加或删除当前选择的一组key
当你向选择添加key时,框选择句柄会出现在所选key的任意一侧,以及顶部和底部。如果向选择添加或删除更多键,句柄将自动调整其位置和大小,以包含所有当前选中的key.
(1).移动选择的key
单击框选择句柄内的任意位置,拖动选中的key并移动它们。你不需要直接点击一个key来做这个,你可以通过单击框选择句柄内的空白空间来拖动。
当你拖拽时,第一个和最后一个key的时间会显示在时间轴栏下,以帮助你把键放在你想要的位置。当选择的key拖动到左边时,任何以负时间结束的key(即时间轴上0标记的左边)都会在释放鼠标按钮时被删除。
(2).缩放选中的key
当你选择了多个键时,你可以缩放选中的key.在曲线模式下,你可以水平缩放以更改key的时间位置,或垂直缩放以更改key的位置。
(3).水平缩放选中的key
在选中key的左边和右边使用框选择句柄水平缩放选择。这改变了key的时间位置,而不修改他们的值。将手柄分开可以延长key经过时间(使选定的动画变慢),或者将key靠得更近,缩短key的经过时间(使选定的动画变快)。
当水平缩放选择时,在视图顶部会显示key的最小和最大时间,以帮助你将你选择的key设置为所需的时间。
(3).垂直缩放选中的key
使用框悬着手柄到所选key的顶部和底部以垂直缩放选择。这将更改key的值,而不修改他们的时间位置。
当你垂直缩放选择时,key的最小和最大时间显示在视图的左侧,以帮助你将选择设置为所需的值。
(4).操纵灰色条
除了出现在所选key周围的框选择句柄外,在curve窗口的顶部和左侧还有灰色操作条,他们提供了操作当前选择的其他方法。
顶部的操作栏允许你修改所选key的时间位置,同时保留它们的值。旁边的栏允许你修改key的值,同时保留它们的时间位置。当你选择多个key时,顶部和右侧的条在两端都显示一个正方形。拖动工具条的中心以移动选中的key(水平或者垂直),或者拖动每个工具条末端的方块以缩放选中的key.
和框选择句柄一样,当使用灰色条移动或缩放选中key时,会显示最小值和最大值或关键帧时间。对于时间操作栏(在窗口的顶部),显示第一个和最后一个关键帧的时间。对于值操作栏(窗口左侧),将显示key的最低值和最高值。
注意:只有当你选择了多个key时,在栏的末端的缩放框才可见,并且视图被缩放到足够长,以显示在每一栏的缩放框。
(5).Ripple 编辑
同上面的Ripple 编辑
14.具有多个运动部件的对象
可能你想要为对象的多个移动部分设置动画,如带有移动镜筒的炮塔或具有许多身体部位的角色。所有部件都可以通过父级上的单个动画组件进行处理,但在某些情况下,在子级上添加其他动画组件很有用
(1).GameObject的子节点动画
GameObject的Hierarchy显示在Animation View左侧的面板中。
你可以通过使用GameObject名称旁边的折叠式三角形来访问游戏对象的子对象。子对象的属性可以像父对象一样设置动画。
或者,在动画录制模式下,你可以只选择想要从Hierarchy面板或者Scene视图中动画化的子游戏对象,并在Inspector中对该对象进行建模或更改其属性。
二、Animation Event
你可以通过使用Animation Events来增加Animation Clips的实用性,Animation Events允许你在time line中指定的点调用对象脚本中的函数。
Animation Event调用的函数还可以选择接受一个参数。参数可以是float、string、int或object引用,也可以是Animation Event对象。AnimationEvent对象具有成员变量,允许将float、string、integer和object引用一次性传递给函数,以及有关触发函数调用的Event和其他信息。
要将Animation Event添加到当前播放头位置的clip,可单击“Event”按钮。将Animation Event添加到Animation中的任何点。双击要在其中触发事件的位置的事件行。添加后,你可以拖动鼠标重新定位事件。要删除事件,请选择它并按Delete键,或右键单击它并选择"Delete Event"
Animation Event允许将数据添加到导入的剪辑中,该剪辑决定了某些动作合适与动画同步发生。例如,对于一个动画角色,你可能想要添加一些事件来说明应该在什么时候播放脚本声。
添加事件时,Inspector窗口会显示几个字段。这些字段允许你指定要调用的函数的名称,以及要传递给它的参数的值。
添加到clips中的事件显示为事件行中的标记。把鼠标放在标记上,以显示带有函数名和参数值的工具提示。
你可以在时间轴中选择和操作多个事件。
要在时间轴中选择多个事件,按住Shift键并逐个选择事件标记,将它们添加到你的选择中。你还可以在它们之间拖动选择框,单击并拖动事件标记区域,如下所示:
例子:
这个例子演示了如何向一个简单的GameObject添加动画事件。在执行所有步骤时,Cube在Play模式中沿x轴向前和向后移动,事件消息在0.8秒后每间隔1秒在控制台显示一次(包括0.8秒)。
这个示例需要一个带有PrintEvent()函数的小脚本。此函数打印一个调试消息,其中包含一个字符串(“called at:”) and the time:
using UnityEngine;
public class ExampleClass : MonoBehaviour
{
public void PrintEvent(string s)
{
Debug.Log("PrintEvent: " + s + " called at: " + Time.time);
}
}
用示例代码创建一个脚本文件,并将其放在你的项目文件夹中(右键单击Unity中的Project窗口并选择Create->C# Script,然后将上面的代码示例复制粘贴到文件中保存)。
在Unity中创建一个Cube GameObject(菜单:GameObject->3D Object->Cube).要向它添加你的新脚本,可以将脚本从Project窗口拖放到Inspector窗口中。
选择Cube然后打开Animation窗口(菜单:Window->Animation)。设置x坐标的位置曲线。
接下来,将x坐标的动画设置为大约0.4,然后在一秒内回到0,然后大约在0.8秒内创建一个动画事件。按下Play以运行动画。
using UnityEngine;
public class AnimationEventTest:MonoBehaviour
{
public void PrintFloat(float theValue)
{
Debug.Log("PrintFloat is called with a value of " + theValue + ":" + Time.time);
}
}
using UnityEngine;
public class AnimationEventTest:MonoBehaviour
{
private Animator mAnimator;
private RuntimeAnimatorController mRuntimeAnimatorController;
private AnimationClip[] clipArray;
void Start()
{
mAnimator = GetComponent();
mRuntimeAnimatorController = mAnimator.runtimeAnimatorController;
clipArray = mRuntimeAnimatorController.animationClips;
int clipCount = clipArray.Length;
for(int i = 0; i < clipCount; ++i)
{
for(clipArray[i].name = "test")
{
AnimationEvent animationEvent = new AnimationEvent();
animationEvent.functionName = "PrintFloat";
//动画末尾
animationEvent.time = clipArray[i].length;
clipArray[i].AddEvent(animationEvent);
}
}
}
public void PrintFloat(float theValue)
{
Debug.Log("PrintFloat is called with a value of " + theValue + ":" + Time.time);
}
}
三、Animator
1.Animator Controllers
Animator Controllers允许你为角色或其他动画游戏对象安排和维护一组动画
controller引用animation clip组件,并使用状态机来管理各种动画状态和它们之间的过渡,可以看做是一种流程图,或者用Unity中的可视化编程语言编写的简单程序。
2.The Animator Controller Asset
当准备使用animation clips时,你需要使用animator controller将它们组合到一起。可以在Unity中创建一个Animator Controller asset,来为一个角色或对象维护一组动画。
Animator Controller asset可以从Assets菜单创建,或者是从Project窗口中的Create菜单创建。
在大多数情况下,拥有多个动画并在某些游戏条件发生时在它们之间切换是正常的。例如,只要按下空格键,你就可以从步行动画切换到跳跃动画。即使你只有一个animation clip,也需要把它放到animator controller中,并附加在GameObject上
controller使用状态机来管理各种动画状态和它们之间的装换,可以被看做是一种流程图,或者用Unity中的可视化编程语言编写的一个简单程序。可以在Animator窗口中创建、查看和修改Animator Controller。
通过附加Animator组件将Animator Controller应用于对象。
3.Animator窗口
Animator窗口允许你创建、查看和修改Animator Controller asserts.
Animator窗口有两个主要部分:主网格布局区和左侧图层以及参数面板。
带有深灰色网格的主要部分是布局区域。你可以使用这个区域来创建、排列和连接Animator Controller中的状态。
你可以右键单击网格来创建一个新的状态节点。使用鼠标中键或Alt/Option拖动移动视图。单击以选择要编辑的状态节点,单击或者拖动状态节点以重新安排状态机的布局。
左边的窗格可以在Parameters视图和Layers视图之间切换。Parameters视图允许你创建,查看和编辑Animator Controller参数。你定义的这些参数将状态机输入的变量。若要添加参数,单击加号图标并从弹出菜单中选择参数类型。要删除参数,可以在列表中选择参数并按下delete键(在macOS上使用fn-Delete删除选中的参数)。
当左侧窗格切换到Layers视图时,你可以在Animator Controller中创建、查看和编辑Layers。这允许在单个Animator Controller中有多个动画层同时工作,每个动画层由独立的状态机控制。这种情况的一个常见用途是在基础层上创建一个单独的层来播放上身动画,该基础层控制角色的一般移动动画
要添加一个图层,可单击加号图标。要删除一个层,选择该层并按下delete键。
打开或关闭"eye"图标将显示或隐藏Parameters和Layers侧窗格,从而允许你有更多的空间查看和编辑你的状态机。
上图是当前状态机内的“breadcrumb”分层位置。状态机可以包含sub-states和trees,且这些结构可以重复嵌套。当深入到子状态时,这里列出了父状态机和正在查看当前状态机。单击父状态机允许你跳转回父状态机,或直接返回到状态机的base layer。
启用锁图标将使Animator窗口锁定在当前状态机上。当锁定图标关闭时,单击新animator asset或具有animator组件的GameObject,将切换animator窗口,以展示当前选中对象的状态机。而锁定窗口允许你保持动画窗口显示之前选中状态机,不管是否选择了其他assets或GameObject。
4.动画状态机
角色或其他动画对象通常有几个不同动画,对应于它在游戏中执行的不同动作。例如,一个角色在空闲时可能会呼吸或轻微摇摆,当被命令行走时,他会惊慌地举起手臂从平台上摔下来。一扇门可能会有开启、关闭、卡住和被打破的动画。Mecanim使用类似于流程图的视觉布局系统来表示状态机,以使你能够控制和排序你想要在角色或对象上使用的Animator clips.
5.状态机基础
基本的思想是一个角色在任何时候都在从事某种特定的行为。可使用的动作将取决于游戏玩法的类型,但典型的动作包括诸如空转、步行、跑步、跳跃等。这些动作被称为状态,在某种意义上,角色处于一个“状态”,在这个状态中它在行走、闲荡或其他什么。一般来说,角色会对它可以进入的下一个状态有限制,而不是能够立即从任何状态切换到任何其他状态。例如,只有当角色已经在跑步时才能执行跑步跳,而不是它处于停顿状态时执行,因此它不应该直接从空闲状态切换到跑步跳状态。角色可以从当前状态进入到下一个状态的选项称为状态转换。总的来说,状态集、转换集合用来记住当前状态的变量构成了状态机。
状态机的状态和转换可以使用图表表示,其中节点表示状态,而弧(节点之间的箭头)表示转换。你可以将当前状态看做是放置在其中一个节点上的标记或突出显示,然后只能沿着其中一个箭头跳到另一个节点。
状态机对于动画的重要性在于,它们可以很容易地设计和更新,而编码相对较少。每个状态都有一个与之关联的运动,只要机器处于该状态就会播放。这使动画师或设计人员能够定义角色动作和动画的可能序列,而不必关心代码如何工作。
(1).状态机
Unity的动画状态机提供了一种方法来概述所有与特定角色相关的动画剪辑,并允许游戏中的各种事件(例如用户输入)触发不同的动画。
可以从Animator Controller窗口设置动画状态机,他们看起来是这样的:
状态机由States、Transitions和Event组成,较小的子状态机可以用做较大状态机中的组件。
6.动画参数
动画参数是在Animator Controller中定义的变量,可以从脚本中访问和赋值。这就是脚本控制和影响状态机流的方式。例如,参数的值可以通过动画曲线来更新,然后从脚本中访问,这样,声音效果的音高可以像动画一样变化。同样,脚本可以设置Mecanim要使用的参数值。例如,脚本可以设置参数来控制Blend Tree.
可以使用Animator窗口的Parameters部分设置默认参数值,可在Animator窗口的右上角选择。它们可以是四种基本类型:
·Int-整数
·Float-带有小数部分的数
·Bool-布尔值(用复选框表示)
·Trigger-布尔值,在转换(由圆形按钮表示)时由控制器重置。
参数可以使用Animator类中的函数从脚本赋值:SetFloat,SetInt,SetBool,SetTrigger和ResetTrigger.
下面是一个基于用户输入和冲突检测修改参数的脚本示例:
using UnityEngine;
public class AnimationEventTest:MonoBehaviour
{
Animator animator;
void Start()
{
animator = GetComponent();
}
void Update()
{
float h = Input.GetAxis("Horizontal");
float v = Input.GetAxis("Vertical");
bool fire = Input.GetButtonDown("Firel");
animator.SetFloat("Forward",v);
animator.SetFloat("Strafe",h);
animator.SetBool("Fire",fire);
}
void OnCollisionEnter(Collision col)
{
if(col.gameObject.CompareTag("Enemy"))
{
animator.SetTrigger("Die");
}
}
}
7.状态机装换
State Machine Transitions的存在是为了帮助你简化大型或复杂的状态机。他们允许你对状态机逻辑有更高级别的抽象。animator窗口中的每个视图都有一个入口和出口节点。这是在State Machine Transitions期间使用的。入口节点是进入状态机后的第一个状态节点。然后将计算入口节点,并根据设置的条件进入目标状态。通过这种方式,入口节点可以通过评估状态机开始时的参数状态来控制状态机开始时的状态。
因为状态机总是有一个默认状态,所以总是会有一个从入口节点到默认状态的默认装换分支。
然后,你可以添加从入口节点到其他状态的额外装换,以控制状态机是否应该以不同的状态开始。
Exit节点用于指示状态机应该退出。
状态机中的每个子状态都被视为一个单独且完整的状态机,因此通过使用这些进入和退出节点,可以更加优雅的控制从父状态机到其子状态机的流
可以将状态机转换与常规状态转换混合,因此可以从状态转换到状态,从状态转换到状态机,从一个状态机直接装换到另一个状态机。
8.State Machine Behaviours
State Machine Behaviour是一类特殊的脚本。以类似的方式将规则的Unity脚本(MonoBehaviours)附加到单独的游戏对象,你可以将StateMachineBehaviour脚本附加到状态机中的单个状态。这允许你编写在状态机进入、退出或保持在特定状态时执行的代码。这意味着你不必编写自己的逻辑代码来测试和检测状态变化。
使用此功能的几个例子可能是:
·当状态进入或退出时播放声音。
·只有在适当的状态下才能执行某些测试(如地面探测)
·激活和控制与特定状态相关的特殊效果。
状态机行为可以以一种非常相似的方式创建并添加到状态,就像你创建并添加脚本到GameObject一样。在状态机中选择一个状态,然后在Inspector中使用“Add Behaviour”按钮选择一个现有的StateMachineBehaviour或创建一个新的脚本。
State Machine Behaviour脚本可以访问Animator enters,updates以及exits等不同状态(或子状态机)时调用的许多事件。以及允许你处理Root motion和IK调用事件。
代码示例:
using UnityEngine;
public class StateMachineBehaviourTest:StateMachineBehaviour
{
override public void OnStateEnter(Animator animator,AnimatorStateInfo stateInfo,int layerIndex)
{
Debug.Log("this is OnStateEnter>>>>>>>>>>> " + animator.name + ":" + stateInfo.ToString() + ":" + layerIndex);
}
override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log("this is OnStateExit>>>>>>>>>>> " + animator.name + ":" + stateInfo.ToString() + ":" + layerIndex);
}
override public void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log("this is OnStateExit>>>>>>>>>>> " + animator.name + ":" + stateInfo.ToString() + ":" + layerIndex);
}
override public void OnStateMove(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log("this is OnStateMove>>>>>>>>>>> " + animator.name + ":" + stateInfo.ToString() + ":" + layerIndex);
}
override public void OnStateIK(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
Debug.Log("this is OnStateIK>>>>>>>>>>> " + animator.name + ":" + stateInfo.ToString() + ":" + layerIndex);
}
}
9.子状态机
角色的复杂性动作通常由多个阶段组成。与其使用单个状态来处理整个操作,不如标识单独的阶段并为每个阶段使用单独的状态。例如,一个角色可能有一个叫做"Trickshot"的动作,它蹲下来瞄准,射击,然后再站起来。
尽管这对于控制目的很有用,但缺点是随着添加更多这些复杂操作,状态机将变得庞大而笨拙。你可以通过在编辑器中使用空白空间可视化地分隔状态组来简化一些事情。但Mecanim更近一步,允许你将一组状态折叠到状态机图中的一个命名项中。这些折叠的状态组称为子状态机。
你可以通过右键单击Animator Controller窗口内的空白空间并从上下文菜单中选择create substate machine来创建子状态机。在编辑器中,子状态机用一个细长的六边形表示,以区别正常状态。
当双击六边形时,当前编辑器将被清除,以允许你编辑子状态机,就好像它本身是一个完全独立的状态机一样。窗口顶部的工具条显示了一个“breakcrumb trail”,以显示当前正在编辑哪个子状态机(注意:你可以在其他子状态机中创建子状态机,等等).
(1).外部条件
如上所述,子状态机只是在编辑器中可视化地折叠一组状态的一种方式,因此当你装换到子状态机时,你必须选择要连接的状态之一。
你将注意到子状态机中的一个额外状态,其名称以up开头。
Up状态表示“outside world”(双击回到父状态机),在视图中包含子状态机的状态机。如果添加从子状态机的状态到Up状态的转换,将提示你选择要连接的上层状态机的状态之一。
10.Animation Layers
Unity使用Animation Layers来管理不同身体部位的复杂状态机。举个例子,如果你有一个下半身的layer用来行走跳跃,还有一个上半身的layer用来投掷物体/射击。
你可以从Animator控制器左上角的layers小部件管理Animation Layers.
在每个layer上,你可以指定Mask(动画模型中应用动画的部分)和Blending类型。Override意味着来自其他层的信息将被忽略,而additive意味着动画将被添加到前一层之上。
你可以通过在小部件上方按下+添加一个新Layer。
Mask属性用于指定此层上使用的掩码。例如,如果你想运行一个模型上半身的扔的动画,并且你的角色在同一时间,还能走路,跑步或者站立,你可以使用一个遮罩在模型上半身投掷动画的Layer中,定义如下:
Layer侧栏中可以看到一个“M”符号,表示该层应用了遮罩。
(1).Animation Layer syncing
有时,能够在不同的层重用相同的状态机是很有用的。例如,如果你想要模拟“受伤”的行为,并且用“受伤”的动画代替“健康”的动画来进行步行/奔跑/跳跃。你可以单击其中一个层上的Sync复选框,然后选择要同步的层。状态机结构将是相同的,但是状态所使用的实际Animation clip将是不同的。
这意味着同步层根本没有自己的状态机定义–相反,它是同步层源的一个实例。在同步层视图中,对状态机的布局或结构所做的任何更改(例如,添加/删除状态或装换)都是对同步层的源进行的。对同步层唯一的更改是在每个状态中使用的选定的动画。
Timing复选框允许动画师根据权重调整同步图层中每个动画的时长。如果没有选择Timing,那么同步层上的动画将被调整,此时同步层的动画将拉伸到原始图层的动画长度。如果选择了这个选项,动画的长度将根据权重取两个动画的平衡值。在这两种情况下(选择和不选择),动画师都会调整动画的长度。如果没有被选中,那么原始图层就是唯一的主图层,如果被选中,那么就会折中处理。
一个’S’符号在层的侧栏中可见,表示该层是一个同步层。
11.Sole和Mute功能
在复杂状态机中,对状态机的部分部件进行操作预览是很有用的。为此,你可以使用Mute/Sole功能。Muting意味着装换将被禁用。Soloed转换是启用的,相对于来自其他同一状态的其他装换。你可以从Transition Inspector或者State Inspector(推荐)中设置Mute和Sole状态,在那里你将对该状态的所有转换有一个概述。
Soloed装换将显示为绿色,而Muted装换将显示为红色,如下图:
在上面的例子中,如果你处于状态0,那么只有装换到状态A和状态B是可用的
·基本的经验法则是,如果一个Sole被勾选,从那个状态的其他过渡将被减弱
·如果同时选中了Sole和Mute,那么Mute优先。
已知问题
·controller图目前并不总是反应引擎内部的mute状态。
12.Target Matching
在游戏中,经常会出现这样一种情况:角色必须以这样一种方式移动,即一只手或一只脚在某一特定时间落在某一地点。例如角色可能需要跳过垫脚石或跳起来捉住头顶的横梁。
你可以使用Animator.MatchTarget函数来处理这种情况。想象一下,例如,你想要安排一个场景,角色跳到一个平台上,你已经有了一个Animation clip,叫做Jump up.首先,你需要在Animation clip中找到角色开始起飞的位置,注意,在这种情况下,在规范化时间内,动画剪辑中的位置是14.1%或0.141.
你还需要在Animation clips中找到角色即将落地的位置,在本例中是78%或0.78
有了这些信息,你就可以创建一个脚本来调用MatchTarget,你可以将它附加到模型中:
using UnityEngine;
using System;
[RequireComponent(typeof(Animator))]
public class TargetCtrl:MonoBehaviour
{
protected Animator animator;
public Transform jumpTarget = null;
void Start()
{
animator = GetComponent();
}
void Update()
{
if(animator)
{
if(Input.GetButton("Firel"))
{
animator.MatchTarget(jumpTarget.position,jumTarget.rotation,AvatarTarget.LeftFoot,new MatchTargetWeightMask(Vector3.one,1f),0.141f,0.78f);
}
}
}
}
脚本将移动角色,使其跳出当前位置,左脚着地。请记住,使用MatchTarget的结果通常只有在游戏玩法中的正确点调用才有意义。
13.Inverse Kinematics(IK)
大多数动画是通过旋转骨骼中的关节角度产生的。子关节的位置随其父关节的旋转而变化,因此,一个关节链的终点可以从它所包含的各个关节的角度和相对位置来确定。这种摆骨骼姿势的方法被称为 forward kinematics(正运动学).
然而,从相反的角度来看待摆放关节的目的是很有用的–给定一个在空间中选定的位置,向后移动,找到一个有效的方法来定位关节,使终点落在那个位置。当你想让一个角色在用户选择的点触碰一个物体,或者让它的脚在凹凸不平的表面上站稳时,这是非常有用的。这种方法被称为Inverse Kinematics(逆运动学:IK),在Mecanim中支持具有正确配置的humanoid角色。
为了设置一个角色的IK,你通常在场景周围有一个角色与之交互的对象,然后通过脚本设置IK,特别是动画功能,比如:SetIKPositionWeight,SetIKRotationWeight,SetIKPosition,SetIKRotation,SetLookAtPosition,bodyPosition,bodyRotation.
在上面的插图中,我们展示了一个角色抓取一个圆柱形物体。我们如何让这一切发生?
我们从一个具有有效Avatar的角色开始。
接下来创建一个Animator Controller,其中至少包含一个角色的动画。然后在Animator窗口的Layers面板中,点击层的锯齿状设置图标,选中弹出菜单中的IK Pass复选框。
确保Animator Controller被分配给角色的Animator组件。
接下来,将一个脚本附加到它上,它实际负责处理IK,我们将其称为IKControl.这个脚本设置了角色右手的IK目标,以及它的外观位置,使它看起来像它所持有的对象。
using UnityEngine;
using System;
using System.Collections;
[RequireComponent(typeof(Animator))]
public class IKControl:MonoBehaviour
{
protected Animator animator;
public bool ikActive = false;
public Transform rightHandObj = null;
public Transform lookObj = null;
void Start()
{
animator = GetComponent();
}
void OnAnimatorIK()
{
if(animator)
{
if(ikActive)
{
if(lookObj != null)
{
animator.SetLookAtWeight(1);
animator.SetLookAtPosition(lookObj.position);
}
if(rightHandObj != null)
{
animator.SetIKPositionWeight(AvatarIKGoal.RightHand,1);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand,1);
animator.SetIKPositon(AvatarIKGoal.RightHand,rightHandObj.position);
animator.SetIKRotation(AvatarIKGoal.RightHand,rightHandObj.rotation);
}
}
else
{
animator.SetIKPositionWeight(AvatarIKGoal.RightHand,0);
animator.SetIKRotationWeight(AvatarIKGoal.RightHand,0);
animator.SetLookAtWeight(0);
}
}
}
}
由于我们不打算让角色的手触及物体的中心(圆柱体的枢轴点),所以我们将一个空对象(在本例中称为“Cylinder Grab Handle”)放置在物体应该放在圆柱体上的位置,并相应的旋转它。然后手瞄准这个子对象。
这个“grab handle”游戏对象应该被指定为IKControl脚本的“Right Hand Obj”属性。
在本例中,我们将look目标设置为圆柱体本身,因此该角色直接朝对象的中心,尽管句柄接近底部。
进入游戏模式,你会看到IK变成了现实。在单击IKActive复选框时观察角色抓取和松开对象,并尝试在playmode中移动圆柱体以看到手臂和手跟随对象。
14.Root Motion-它是如何工作的
(1).Body Transform
Body Transform是角色的重心。在Mecanim的重定位引擎中使用,提供了最稳定的位移模型。Body Orientation是相对于Avatar T-Pose姿势的上下身体方向的平均值。
Body Transform和Orientation存储在Animation Clip中(使用Avatar中建立的肌肉定义)。它们是Animator Clip中唯一保存的世界空间曲线。其他的一切:肌肉曲线和IK目标(手和脚)是相对于body transform存储的。
(2).Root Transform
Root Transform是Body Transform在Y平面上的投影,在运行时计算。在每一帧,计算Root Transform的变化。然后将转换中的更改应用到游戏对象,使其移动。
(3).Animation Clip Inspector
Animation Clip Editor settings-Root Transform Rotation,Root Transform Position(Y)以及Root Transform Position(XZ)-让你控制Root Transform投影从Body Transform.根据这些设置Body Transform转换的某些部分可能被转移到Root Transform.例如,你可以决定是否将运动Y位置作为Root Motion(轨迹)的一部分,还是作为体位(body transform)的一部分,这就是所谓的Baked into Pose.
以下如果太绕可查看参考资料【Root Motion深度解析】
(4).Root Transform Rotation
Bake into Pose:方向将停留在body transform(或者pose)上。Root Qrientation是常数,以及方向是恒等的。这意味着游戏对象不会被Animation Clip旋转。只有类似启动和停止Root Qrientation才应该使用这个选项。在UI中会有一个绿灯告诉你Animation clip是一个很好的候选。一个合适勾选这个选项的情景是,步行或者跑步动画。
Based Upon:这允许你设置Clip的方向。使用Body Orientation,clip将定向跟随身体的向前矢量。这种默认设置对于大多数运动捕捉(Mocap)数据(比如行走,跑步和跳跃)都很有效,但是如果运动垂着与身体的向前向量,就会像扫射一样失败。在这些情况下,你可以使用偏移设置手动调整方向。最后在导入clip,你将发现原始的自动添加了编辑的偏移。它通常和keyframed数据一起使用,以尊重美术设定的方向。
Offset:用于在选择了BaseUpon后输入偏移量。
(5).Root Transform Position (Y)
这使用了跟Root Transform Rotation相同的概念
Bake Into Pose:运动的Y分量将停留在Body Transform(姿势上)。Root Transform变换的Y分量是常数,Delta Root PositionY是0.这意味着clip不会改变游戏对象的高度。同样的,UI上会有一个绿灯告诉你,一个clip是一个很好的候选将Y轴的运动烘焙到pose中。大多数AnimationClips将启用这个设置。只有会改变游戏对象高度的clip应该关闭这个功能,比如跳上或调下。
注意:Animator.gravityWeight是由Bake Into Pose position Y驱动的。启用时,gravityWeight = 1,禁用时,gravityWeight=0,在状态之间切换时,clip中的gravityWeight会混合。
Based Upon:跟Root Transform类似,你可以从Original或者Mass Center(Body)中选择。还有一个Feet的选项,这对于AnimationClips是非常方便的,它可以改变高度(禁用Bake Into Pose时)。当使用Feet,Root Transform Position Y将匹配所有帧中最低的脚的Y值。因此,混合点始终保持在脚的周围,以防止当混合或过渡时的浮动问题
Offset:与Root Transform Rotation类似,你可以使用Offset设置手动调整AnimationClip高度
(6).Root Transform Position(XZ)
同样,这使用了Root Transform Rotation和Root Motion Position(Y)中描述的相同概念。
Bake Into Pose:通常用于"Idles“,当你想强力使Position(XZ)的delta为0时。在多次评价后,可以防止delta的累积漂移。它也可以用于一个keyframe clip在Base Upon Original时,强力编辑位置为美术的设置。
(7).Loop Pose
Loop Pose(就像在Blend Trees中的Pose Blending或者Transitions)发生在Root Transform的引用中。一旦计算出Root Transform,Pose将会与它相对应。计算了开始帧和结束帧之间的相对Pose插值,分布在从0到100%的clip范围内。
(8).Generic Root Motion 以及 Loop Pose
它的工作原理和Humanoid Root Motion基本相同,但是它没有使用Body Transform来计算Root Transform,而是使用Root Node.Pose(所有在Root Motion骨骼下变形的骨骼)都是相对于Root Transform变化形成的
15.教程:为"in-place"humanoid动画编写Root Motion脚本
有时候你的动画是"in-place(原地)“的,这意味着如果你把它放在一个场景中,它不会移动到它所在的角色。换句话说,动画不包含"root motion”.为此,我们可以从脚本修改root motion.按照下面的步骤将所有东西组合在一起(注意,实现相同的结果有很多不同的方法,这只是一个方法).
·打开包含"in-place"动画的FBX文件的Inspector,并转到animation选项卡
·确保Muscle Definition设置为你想要控制的角色(假设这个角色被称为Dude,并且它已经被添加到Hierarchy视图中)
·从可用的clip中选择Animaion clip
·确保Loop Pose正确对齐(旁边的灯是绿色的),并单击Loop Pose复选框
·在animation视图中预览动画,以确保动画的开始和结束平滑对齐,并确保角色正在“原地”移动
·在动画剪辑上创建一条曲线来控制角色的速度(你可以从Animation Import inspector Curves->+中添加一条曲线)
·给这条曲线取个有意义的名字,比如"Runspeed"
·创建一个新的Animator Controller(我们称之为RootMotionController)
·将所需的动画剪辑放入其中,这将创建一个具有动画名称的状态(比如Run)
·向与曲线同名的Controller添加一个参数(在本例中为"Runspeed")
·选择Hierarchy中的角色Dude,其Inspector应该具有Animator组件
·将RootMotionController拖放到动画器的控制器属性上。
·如果你现在按下play,你会看到"Dude"在原地跑着。
最后,为了控制运动,我们需要创建一个脚本来实现OnAnimatorMove回调。
using UnityEngine;
[RequireComponent(typeof(Animator))]
public class RootMotionScript:MonoBehaviour
{
private void OnAnimatorMove()
{
Animator animator = GetComponent();
if(animator)
{
Vector3 newPosition = transform.position;
newPosition.z = animator.GetFloat("Runspeed") * Time.deltaTime;
transform.position = newPosition;
}
}
}
你应该附加RootMotionScript.cs指向"Dude“对象。这样做时,Animator组件将检测到脚本具有OnAnimatorMove函数,并显示由script处理的Apply Root Motion属性。
16.Blend Trees
在游戏动画中一个常见的任务是混合两个或多个相似的动作。也许最著名的例子是根据角色的速度混合了行走和奔跑的动画。另一个例子是一个角色在奔跑时向左或向右倾斜。
区分Transitions和Blend Trees是很重要的。虽然两者都是用来创建平滑的动画,他们是用于不同的情况。
·Transitions(转换)用于在给定的时间内平稳地从一个动画状态过渡到另一个动画状态.Transitions被指定为动画状态机的一部分。从一个motion过渡到一个完全不同的motion通常是好的,如果转换是快速的。
·Blend Trees用于允许多个动画平滑的混合,通过不同程度地合并它们的部分。每个动作对最终效果的贡献大小由混合参数控制,它只是与Animator Controller相关的数字动画参数之一。为了使混合motion有意义,混合的motion必须具有相似的性质和时间。Blend Trees是Animation State Machine中一种特殊的状态类型。
类似动作的例子可以是各种各样的行走和奔跑动画。为了使混合效果更好,clip中的动作必须在相同的时间点进行。例如。可以将步行和跑步动画对齐,使脚与地面接触的时刻在相同的时间点发生(例如,左脚在0.0处,右脚在0.5处),由于使用的是normalized时间,因此clip的长度是否不同并不重要。
(1).使用Blend Trees
要开始使用新的Blend Tree,你需要:
1.右键单击Animator Controller窗口上的空白区域
2.从出现的上下文菜单中选择Create State->From New Blend Tree
3.双击Blend Tree以进入Blend Tree Graph
Animator窗口现在显示了整个Blend Tree,而Inspector显示当前选中的节点以及其直接子节点。
要将Animation Clips添加到Blend Tree中,你可以选择Blend Tree,然后在Inspector中的motion字段中单击加号图标。
或者,你可以通过右键单击Blend Tree,并从上下文菜单中选择添加animation clips或者子混合节点。
当用Animation clips和输入参数设置Blend Tree时,Inspector窗口将显示当数值发生变化时动画是如何组合的(当拖动滑块时,树根节点上的箭头将改变其阴影以显示主导Animation Clip)
你可以选择Blend Tree中的任何节点,以便在Inspect中检查它。如果选择的节点是Animation Clip,则会显示该Animation Clip的Inspector.如果从模型导入动画,设置将是只读的。如果该节点是一个Blend Node,将显示Blend Nodes的Inspector.
你可以从Blend Type菜单中选择1D或2D混合。
(2).Blend Trees以及Root Motion
动画之间的混合使用线性插值处理(例如,每个动画的数量是由混合参数加权的独立动画的平均值)。你应该注意到Root Motion不是以相同的方式插值的。
17.1D Blending
Blend Node在Inspector中的第一个选项时Blend类型。这个下拉菜单用于选择可以根据一个或两个参数进行混合的不同混合类型之一。1D Blending根据单个参数混合子motions.
在设置混合类型之后,首先需要选择控制这个Blend Tree的动画参数。在本例中,参数为方向,在-1.0(左)和+1.0(右)之间变化,0.0表示不倾斜的直线运行。
然后,你可以通过单击“+”按钮并从弹出菜单中选择add Motion Field添加单个动画。当你完成时,它应该看起来像这样:
Inspector顶部的图标显示了当参数在其最小值和最大值之间变化时,每个子motion的影响。每个motion显示为一个小的蓝色金字塔(第一个和最后一个只显示了一半),如果你点击并按住其中一个鼠标左键,响应的motion在下面的motion列表中高亮显示。每个金字塔的峰值定义了motion有充分影响的参数值,即其动画权重为1,其他动画权重为0.这也被称为motion的阈值(threshold)
红色的竖线表示参数的值。如果你在Inspector底部的预览中按下Play,并在图表中左右拖动红色条,你可以看到参数的值如何控制不同motion的混合。
(1).Parameter Range
混合树所使用的参数范围如下图所示,为左边和右边两个数字。它们中的任何一个都可以通过点击数字和用鼠标左右拖动来改变。注意,这些值对应于motion列表中第一个和最后一个motion的阈值。
(2).Thresholds
你可以通过单击图表中相应的蓝色金字塔并将其向左或向右拖动来更改motion阈值。如果“Automate Thresholds”切换不启用,你还可以通过在阈值列中的number字段中键入数字来编辑motion列表中的motion的阈值。
motion列表下面是复选框自动阈值。启用它将在参数范围内均匀分布motion阈值。例如,如果有5个剪辑,并且参数范围在-90到+90之间,那么依次将阈值设置为-90、-45、0、+45和+90.
Compute Thresholds下拉列表将从Animation Clips中的root motions获得的数据设置阈值。可供选择的数据是速度,速度x,速度y,或速度z,以及角度或弧度的角速度。如果参数对应于这些属性中的一个,则可以使用compute threshold下拉列表来计算阈值。
Property | Function |
---|---|
Speed | 根据速度(速度大小)设置每个motion的阈值 |
Velocity X | 根据velocity.x设置每个motion的阈值 |
Velocity Y | 根据velocity.y设置每个motion的阈值 |
Velocity Z | 根据velocity.z这只每个motion的阈值 |
Angular Speed(Rad) | 根据每个motion的角速度(以弧度/秒为单位)设置阈值 |
Angular Speed(Deg) | 根据每秒钟角度的角速度设置每个motion的阈值 |
例如:你有一个walk动画每秒1.5个单位,慢跑速度为每秒2.3个单位,跑步速度为每秒4个单位,从下拉菜单中选择Speed选项将根据这些值设置三个动画的参数范围和阈值。
18.2D Blending
Blend Node节点检查器中的第一个选项时Blend Type.这个下拉菜单的选择可以根据一个或两个参数进行混合的不同混合类型之一。2D混合类型根据两个参数对子motion进行混合。
不同的2D混合类型有不同的用途。它们在计算每个motion的影响方面有所不同。
2D Simple Directional:当你的动作代表不同的方向时最好用,比如“向前走”、“向后走”、“向左走”、“向右走”,或者“向上瞄准”,“向下瞄准”,“向左瞄准”,“向右瞄准”。可选的,在位置(0,0)的单个动作可以包括在内,例如"idle"或者“ain straight”。在Simple Directional类型中,同一个方向不应该有多个动作,比如“向前走”和“向前跑”
2D Freeform Directional:当你的动作代表不同的方向时,也可以使用这种混合类型,但是你可以在同一个方向有多个动作,例如“向前走”和“向前跑”。在Freeform Directional类型中,motions集合始终包含位置(0,0)上的单个motion,例如"idle".
2D Freeform Cartesian:当你的动作不代表不同的方向时最好使用。使用Freeform Cartesian,你的X参数和Y参数可以代表不同的概念,比如角速度和线速度。例如“向前走没有转弯”,“向前跑没有转弯”,“向前走右转”,“向前跑右转”等等。
Direct:这种混合树可以让用户直接控制每个节点的权重。用于面部形状或随机idle的混合。
在设置完Blend Type之后,你需要做的第一件事是选择两个控制Blend Tree的Animation Parameters.在这个例子中,参数是velocityX(strafing)和velocityZ(forward speed)
然后,你可以通过单击±>add Motion Field向BlendTree添加一个Animation Clip来添加单个动画。当你完成的时候,它看起来像这样:
2D混合中的position类似于1D混合中的thresholds,只是有两个值而不是一个,对应于两个参数中的每一个。它们沿水平x轴的位置对应于第一个参数,沿垂直Y轴的位置对应于第二个参数。一个向前行走的动画可能有0的velocityX和1.5的velocityZ,所以这些值应该输入到PosX和PosY数字字段中。
(1).The 2D Blending Diagram
Inspector顶部的图表显示了2D混合空间中子motions的位置。motion用蓝点显示。没有指定Animation Clip或者Blend Tree的motion对混合没有影响,显示为灰色点。你可以通过单击图表中的点来选择motion。一旦选定,该motion对混合空间中的每个点的影响将被视为蓝色场。motion位置下的场最强,motion影响最大,即动画权值为1,其他动画权值为0.再远一点,随着其他motion的影响逐渐减弱。
红点表示两个参数的值。如果你在Inspector底部的预览中按下Play并拖动图表中的红点,你可以看到参数的值如何控制不同motion的混合。在这个图中,你也可以看到每个motion的影响被表示为每个motion的圆周。你会发现,如果你把代表motion的蓝点上的红点移动,这个motion的圆就会得到它的最大半径,而其他motion的圆就会缩小到零。在处于几个motion之间的位置,附近的多个motion将会混合产生影响。如果你选择一个motion来观察这个motion的蓝色影响场,你可以看到当你移动红点的时候,这个motion的圆的大小和不同位置的影响场的强度是一致的。
当没有选择motion时,这个图显示了所有的影响场的混合,在单一motion占主导的情况下是更蓝的,而在许多motion导致混合的情况下相对不那么蓝。
(2).Positions
你可以通过单击图中对应的蓝点并拖动它来更改motion的位置。你还可以通过在PosX和PosY列中的number字段中键入数字来编辑motion在motion列表中的位置坐标。
Compute Positions下拉菜单将根据Animation clip中的root motions获得的数据设置位置。可供选择的数据是速度,速度x,速度y,或速度z,以及角度或弧度的角速度。如果你的一个或两个参数对应于这些属性中的一个,你可以使用Compute Positions下拉菜单计算Pos X和PosY.
Property | Function |
---|---|
Velocity XZ | 根据每个motion的velocity.x设置每个motion的PosX,根据每个motion的velocity.z设置PosY |
Speed And Angular Speed | 根据角速度(以弧度/秒为单位)设置每个motion的PosX,根据速度设置每个motion的PosY |
此外,你可以通过选择Compute Position->X Position From和/或Compute Position->Y Position From来混合和匹配,每次只计算其中一个位置,而不改变另一个位置。
Property | Function |
---|---|
Speed | 根据每个motion的速度(速度的大小)设置每个motion的PosX或PosY |
Velocity X | 根据velocity.x设置每个motion的PosX或PosY |
Velocity Y | 根据velocity.y设置每个motion的PosX或PosY |
Velocity Z | 根据velocity.z这只每个motion的PosX或PosY |
Angular Speed(Rad) | 根据每个motion的角速度(以弧度/秒为单位)设置每个motion的PosX或PosY |
Angular Speed(Deg) | 根据每个motion的角速度(以角度/秒为单位)设置每个motion的PosX或PosY |
例如,你的参数对应于横向速度和向前速度,你有一个平均速度(0,0,0)的空闲动画,一个带有(0,0,1.5)的步行动画,以及两个速度分别为(-1.5,0,0,0)和(1.5,0,0)的strafe动画。从下拉菜单中选择速度XZ选项,将根据速度的X和Z坐标设置motion的位置。
19.Direct Blending
使用Direct Blend Tree允许你将animator参数直接映射到Blend Tree子对象的权重。如果你想精确地控制正在混合的各种动画,而不是使用一个或两个参数间接地混合他们(在1D和2DBlend Tree的情况下),这可能是有用的。
当设置一个Direct Blend Tree时,Inspector允许你向motion列表添加motion.然后应该为每个motion分配相应的参数,以直接控制它在树中的混合权重。
实际上,这种Direct模式简单地绕过了交叉衰减,或者各种2D混合算法(Freeform Directional,Freeform Cartesian等),并允许你实现任何你想要控制混合动画混合的代码。
这对于混合面部表情的混合变形动画或混合添加的动画特别有用。
20.其他Blend Tree选项
下面的选项对于1D和2D混合都是通用的。
(1).Time Scale
你可以使用animation speed数字字段(顶部带有时钟图标的列)来修改animation clip的“自然”速度,因此你可以使用2.0的值使行走速度增加一倍。Adjust Time Scale > Homogeneous Speed按钮重新调整clips的速度,使其与所选的参数的最小值和最大值相对应,但保持最初的相对速度不变。
注意:只有当所有的motion都是animation clip时,才可以使用“Adjust Time Scale”,而子节点不能是Blend Tree。
(2).Mirroring
你可以在motion列表中镜像任何humanoid Animation Clip,方法是让镜像在最右边切换。这个特性使你可以在原始格式和镜像版本中使用相同的动画,而不需要两倍的内存和空间。
21.Animation Blend Shapes
(1).美术准备
一旦你在Maya设置了BlendShapes
·将你的选择导出到fbx,确保选中动画框,并且需要blend Shape的模型选中blend Shape
·将fbx文件导入unity(assets->import new assets->[name of file].fbx)
·把asset拖放到hierarchy窗口中。如果在hierarchy中选择对象并在inspector中查看,你将看到Blend Shapes在SkinnedMeshRenderer组件下列出。在这里,你可以将blend shape的影响调整为默认形状,0表示benld shape没有影响,100表示blend shape完全影响。
(2).在Unity创建动画
也可以在Unity中使用Animation窗口来创建blend animation,步骤如下:
·在Window->Animation->Animation下打开Animation窗口
·在窗口的左边点击"Add Curve",添加一个blend shape,它将在skinned mesh renderer下。
从这里你可以操作keyframes和blend weights来创建所需的动画。
一旦你完成了你的Animation编辑,你可以在编辑器窗口点击Play或在Animation窗口预览你的动画。
(3).脚本访问
还可以使用GetBlendShapeWeight和SetBlendShapeWeight等函数通过代码设置混合权重。
通过访问blendShapeCount变量以及其他有用的函数,还可以检查Mesh上有多少blend shapes.
下面是一个代码示例:当附加到一个包含3个或3个以上blend shape的gameobject时,它将一个默认shape混合成另外两个blend shape.
using UnityEngine;
using System.Collections;
public class BlendShapeExample:MonoBehaviour
{
int blendShapeCount;
SkinnedMeshRenderer skinnedMeshRenderer;
Mesh skinnedMesh;
float blendOne = 0f;
float blendTwo = 0f;
float blendSpeed = 1f;
bool blendOneFinished = false;
void Awake()
{
skinnedMeshRenderer = GetComponent();
skinnedMesh = GetComponent().sharedMesh;
}
void Start()
{
blendShapeCount = skinnedMesh.blendShapeCount;
}
void Update()
{
if(blendShapeCount > 2)
{
if(blendOne < 100f)
{
skinnedMeshRenderer.SetBlendShapeWeight(0,blendOne);
blend0ne += blendSpeed;
}
else
{
blendOneFinished = true;
}
if(blendOneFinished == true && blendTwo < 100f)
{
skinnedMeshRenderer.SetBlendShapeWeight(1,blendTwo);
blendTwo += blendSpeed;
}
}
}
}
22.Animator Override Controllers
Animator Overrider Controller是一种asset类型,允许你扩展现有的Animator Controller,替换特定的动画,但保留原始结构、参数和逻辑。
这允许你创建相同基本状态机的多个变体,但每个变体使用不同的动画集。例如,你的游戏可能有各种各样的NPC类型生活在世界上,但每种类型(小妖精、食人魔、精灵等)都有自己独特的动作,可用于行走、空转、坐姿等。
通过创建一个包含所有NPC类型逻辑的"base" Animator Controller,你可以为每种类型创建一个覆盖此"base"的状态机并放入各自的动画文件。
下面是一个典型的Animator Controller asset
下图代表一个Animator Controller,它包含一个简单的状态机,其中混合树控制四个方向的动画,加上一个空闲动画
为了扩展这个通用的NPC状态机以使它适用于例如:食人魔角色的独特动画,你可以创建一个Animator Override Controller并用食人魔的animation clips替换原始animation clips。食人魔可能有不同的怠速和移动方式,可能是较慢,较沉重或者更肌肉的运动。使用Animator Override Controller,可以在具有不同动画集的不同角色之间共享如何在不同运动状态之间进行转换和混合的基本逻辑,从而减少构建和修改状态机本身所需的工作
要创建新的Animator Overrider Controller。使用Assets->Create菜单或Project视图中的Create按钮,然后选择Animator Overrider Controller
Animator Override Controller具有与Animator Controller非常相似的图标,只是它在图标的一角有一个“加号”符号而不是“播放”符号
在Inspector中选择新的Animator Override Controller时,它最初没有分配Animator Controller.如下所示:
如果使用Override Controller,你需要在Inspector面板将原始controller asset分配给新的Override Controller。完成此操作后,原始控制器中使用的所有动画将显示在Override Controller的Inspector面板上。
可以指定新的Animation Clips覆盖原始Animation Clips。在此示例中,所有clips都被“Ogre”版本覆盖。
这个Override Controller可以在Ogre角色的GameObject的animator组件中使用,就像他是一个Animator Controller一样。它将与原始的Animator Controller具有相同的逻辑,但播放的是新分配的动画而不是原始动画。
23.Retargeting of Humanoid animations
Mecanim最强大的功能之一是retargeting of humanoid animations。这意味着你可以相对轻松的将同一组动画应用于各种角色模型。retargeting只适用于配置了Avatar的humanoid模型,因为这样可以让我们在模型的骨骼结构之间建立对应关系。
(1). 推荐的Hierarchy结构
使用Mecanim动画时,你可以包含以下元素
·导入具有Avatar的角色模型
·引用Animator Controller asset的Animator组件
·被Animator Controller引用的Animation Clips
·角色的相关脚本
·与橘色相关的组件,例如Character Controller
你的项目还应包含另一个具有有效Avatar的角色模型
推荐的设置是:
·在Hierachy中创建具有角色相关组件的GameObject
·将模型作为GameObject的子节点与Animator组件一起使用
·确保引用Animator的脚本正在寻找子节点中的Animator而不是根节点的Animator.使用GetComponentInChildren()来代替GetComponent()。
·禁用原始模型
·将所需模型作为GameObject的另一个子节点放入
·确保新模型的Animator Controller属性引用相同的controller asset
·调整根节点GameObject上的character controller,transform,以及其他属性,以确保动画与新模型平稳运行。
24.性能和优化
(1).Character设置
骨骼数量
在某些情况下,你可能需要创建具有大量骨骼的character:例如,当你需要大量可自定义的附件时。这些额外的骨骼增加了构建的大小,并且每个额外的骨骼可能具有相对的处理成本。例如:在通用模式下,已经拥有30个骨骼rig上的15个额外骨骼需要花费50%的时间解决。注意:你可以为Generic和Humanoid类型添加其他骨骼。如果你没有是引用其他骨骼播放动画,则处理成本应该可以忽略不计。如果附件不存在或隐藏,则此成甚至更低。
多个Skinned Meshes
尽可能合并skinned meshes.将角色拆分为两个Skinned Mesh Renderers会降低性能。如果你的角色只有一种材质,是比较好的情况,但在某些情况下,你可能需要不止一种材质
(2).Animation系统
Controllers
当Controller未设置时,Animator不会花时间处理
简单的animation
使用Animator播放没有混合的单个Animation Clip比传统动画系统更慢。旧的动画系统对曲线进行采样并直接写入变换。Unity的当前动画系统Animator具有用于混合的临时缓冲区,并且还可以对采样曲线和其他数据进行额外复制。当前系统布局已针对动画混合和更复杂的设置进行了优化。
Scale Curves
为Scale设置动画曲线比动画的平移和旋转曲线更耗费性能。为了提高性能,请避免使用缩放动画。
注意:这不适用于常量曲线(Animation Clip中值不变的曲线)。常量曲线经过优化,比普通曲线更省性能。与默认场景值具有相同值的常量曲线不会每帧写入场景。
Layers
大多数情况下,Unity都在估算动画,并将动画层和动画状态机的开销降至最低。向animator添加另一个Layer(无论是否同步)的成本取决于Layer播放的动画和blend trees.当Layer的权重为0时,Unity会跳过Layer update。
Humanoid与Generic动画类型
·导入Humanoid动画时,如果不需要IK Goal或者finger动画,可使用Avatar遮罩(class-AvatarMask)将它们移除。
·使用Generic时,使用rootmotion比不使用它还耗性能。如果你的动画不使用root motion,请确保未指定root bone
场景级优化
·使用hashes而不是字符串来查询Animator
·实现一个小的AI Layer来控制Animator.你可以使它为OnStateChange,OnTransitionBegin和其他事件提供简单的回调。
·使用State Tags可以轻松地将AI状态机与Unity状态机匹配
·使用其他曲线来模拟事件
·使用其他曲线标记动画:例如与MatchTarget一起使用
运行时优化
(1).Visibility以及Updates
始终通过将animator的Culling Mode设置为Base on Renderers来优化动画,并禁用skinned mesh renderer的Update When OffScreen属性。这样可以避免Unity在角色不可见时更新动画。
25.Animator组件
Animator组件用于将动画分配给场景中的GameObject。Animator组件需要引用Animator Controller,它定义了要使用的Animation Clip,并控制何时以及如何在它们之间进行混合和转换。
如果GameObject是具有Avatar定义的Humanoid角色,则还应在此组件中指定Avatar.如下所示:
下图显示了各种assets(Animation Clips,Animator Controller以及Avatar)如何通过GameObject的Animator组件组合在一起
(1).Properties
Property: | Function: |
---|---|
Controller | 附加到此角色的animator controller |
Avatar | 这个角色的Avatar(如果Animator用于hunmanoidjuese) |
Apply Root Motion | 我们应该从动画本身还是从脚本控制角色的位置和旋转 |
Update Mode | 这允许你选择Animator何时更新,以及它应使用的timescale。Normal:Animator和Update调用同步更新,Animator的速度与当前timescale匹配。如果timescale变慢,Animations将减慢以匹配。Animate Physics:Animator与FixedUpdate调用同步更新(即与物理系统锁定步骤)。如果你的动画涉及到物理交互,例如:可以推动rigidbody对象的角色,则应使用此模式。Unscaled Time:Animator与Update调用同步更新,单Animator的速度忽略当前timescale,并且无论如何都以100%的速度运行动画。这对于以正常速度制作GUI系统,同时为了特殊效果修改timescale或暂停游戏是非常有用的 |
Culling Mode | 你可以选择动画的剔除模式Always Animate:总是运行动画,即使在屏幕外也不要剔除。Cull Update Transforms:当renderers不可见时,将禁用Retarget,IK,和写入Transform。Cull Completely:当renderers不可见时,动画将完全禁用。 |
(2).Animation curve信息
Animator组件底部的信息框为你提供Animator Controller使用的所有clips的数据明细
Animation clip包含“Curves”形式的数据,表示值随时间的变化情况。这些curves可以描述对象的位置或旋转,humanoid animation系统中的肌肉的弯曲,或者clip内的其他动画值,诸如改变的material颜色
下图表示每个数据项代表的内容
Label | Description |
---|---|
Clip Count | 分配给此Animator Controller的animation clips总数 |
Curves(Pos,Rot&Scale) | 用于表示对象的位置、旋转或缩放的动画曲线总数。这些是用于不属于标准humanoid rig的动画对象。在为humanoid avatar设置动画时,这些曲线会显示额外非肌肉骨骼的计数,例如尾巴、飘逸的布料或悬挂的吊坠。如果你有humanoid动画并且你注意到意外的非肌肉animation curves,则你的动画文件中有不必要的动画曲线。 |
Muscles | 此Animator用于humanoid animation的肌肉动画曲线的数量。这些是用于为标准humanoid avatar肌肉制作动画的曲线。除了Unity标准avatar的标准肌肉运动外,还包括两条"muscle curve",用于存储root motion位置和旋转动画。 |
Generic | animator用于为其他属性(例如material color)设置动画的数字(float)曲线的数量 |
PPtr | sprite动画曲线的总数(由Unity的2d系统使用) |
Curves Count | 动画曲线的总合计数 |
Constant | 优化为常量(不变)值的动画曲线数。如果动画文件包含具有不变值的曲线,Unity会自动选择此选项 |
Dense | 使用"dense"存储数据的方法优化的动画曲线的数量(线性插值的离散值).与"stream"方法相比,此方法使用的内存少得多 |
Stream | 使用存储数据的"stream"方法的动画曲线的数量(具有时间的值和用于曲线插值的切线数据)。该数据比"dense"方法占用更多的内存 |
如果导入Animation clips时Animation import reference中的"Anim Compression"设置为"Optimal",Unity将使用启发式算法来确定使用dense还是stream存储每条曲线的数据。
26.Animator Controller
Animator Controller允许你为角色或者对象排列和维护一组Animation Clips以及关联的Animation Transitions。在大多数情况下,拥有多个动画并在某些游戏条件发生时在它们之间切换是正常的。例如,只要按下空格键,你就可以从步行Animation Clip切换到跳跃Animation Clip。即使你只有一个Animation Clip,仍需要将其放入Animator Controller中以在GameObject上使用它。
Animator Controller引用了Animation Clips,并使用状态机管理各种动画片段和它们之间的过渡,可以将其视为Animation Clip的流程图或者用Unity的可视化编程语言编写的简单程序用于控制动画间的过渡。
当你使用Animation窗口开始设置GameObject动画时,或者将Animation Clip附加到GameObject时,Unity会自动创建Animator Controller。
要手动创建Animator Controller,请右键单击Project窗口,然后单击Create->Animator Controller。
(1).Navigation(导航)
使用鼠标上的滚轮或等效项放大和缩小Animator Controller窗口。
要关注Animator Controller的某个地方时,可以选择一个或多个状态(单击或拖动要选择的状态周围的选择框),然后按F键放大选择。
按A键使所有Animation states适合Animator Controller视图
Unity会保留你之前的选择。按A键和F键可在所选动画状态和整个Animator Controller之间切换。
在Play Mode期间,Animator会平移视图,以便始终可以看到正在播放的当前状态。Animator Controller尊重基本层和子状态机的独立缩放因子,窗口自动平移以确保活动状态的可见性。
要做Play Mode下修改缩放大小,可以用以下步骤
·在Animator Controller窗口中启用Auto Live Link
·点击Play按钮进入Play Mode
·点击Pause
·在Animator Controller中,选择要放大的states
·按F键放大你选择的states
·再次单击Play按钮可恢复PlayMode
27.创建Animator Controller
(1).Animator Controller
你可以从Animator Controller视图(菜单:Window->Animation->Animator)查看和设置角色行为。
可以创建Animator Controller的各种方法
·从Project视图选择Create->Animator Controller
·右键单击Project View 并选择Create->Animator Controller
·从Assets菜单中选择Assets->Create->Animator Controller
他在磁盘上创建了一个.controller asset.在Project窗口中,图标如下所示:
(2).Animation窗口
完成状态机设置后,你可以将控制器拖放到Hierarchy视图中具有Avatar的任何橘色的Animator组件上。
Animator Controller窗口包含:
·Animation Layer Widget(左上角)
·Event Parameters Widget(左上角)
·状态机本身的可视化视图
Animator Controller窗口将始终显示最近选择的.controller asset的状态机,无论当前加载的是什么场景
28.Animation States
Animation States是Animation State Machine的基本构建块。每个状态都包含一个单独的动画序列(或者blend tree),当角色处于该状态时,它将播放。当游戏中的事件触发状态转换时,角色将处于新状态,并使用新状态的动画序列。
在Animator Controller中选择状态时,你将在Inspector中看到该状态的属性。
Property | Function |
---|---|
Speed | 动画的默认速度 |
Motion | 分配给此状态的Animation Clip |
Foot IK | 是否需要Foot IK的状态,适用于Humanoid animations |
Write Defaults | AnimatorStates是否回写未通过其Motion动画的属性的默认值(退出当前状态时,恢复之前的值) |
Mirror | 动画是否需要镜像。这仅适用于Humanoid animations |
Transitions | 源自此transitions的转换列表 |
以棕色显示的默认状态是状态机首次激活时的状态。如果有必要,可以通过右键单击其他状态,并从右键菜单中选择"Set As Default"来更改默认值。sole和mute复选框用于控制动画预览的行为。
通过右键单击Animator Controller窗口中的空白区域并从上下文菜单中选择Create State->Empty,可以添加新状态。或者你可以将动画拖动到Animator控制器窗口中以创建包含该动画的状态。(注意,你只能将Mecanim动画拖动到Controller中-非Mecanim动画将被拒绝。)
(1).Any State
Any State是一个永远存在的特殊状态。它适用于你想要进入特定状态的情况,无论你当前处于哪个状态。这是向状态机中的所有状态添加相同向外转换的简便方法。注意,Any State的特殊含义意味着它不能成为转换的终点(即跳转到"any state"不能用作选择随机状态进入下一个的方式)
29.Animation transitions
Animation transitions允许状态机从一种动画状态切换或混合到另一种动画状态。Transitions不仅定义了状态之间的混合应该持续多长时间,而且还定义他们应该在什么条件下激活。你可以设置仅在特定条件为真时才发生转换。要设置这些条件,可以在Animator Controller中指定参数值。
例如,你的角色可能具有“巡逻”状态和“休眠”状态。你可以将巡逻和休眠之间的转换设置为仅在“alertness”参数值低于某个级别时才会发生。
要为transitions命名,可在字段中键入名称,如下所示
状态的Inspector窗口显示状态使用的transitions,如下所示:
在任何给定时间只能有一个transition活动。但是,如果设置为允许中断,那么当前活动的transition可能会被另一个transition中断。
(1).Transition properties
要查看transition属性,可单击Animator窗口中连接两个状态的过渡线。属性将显示在Inspector窗口
使用以下属性调整transition以及它在当前状态和下一状态之间的混合方式
Property | Function |
---|---|
Has Exit Time | Exit Time是一种不依赖于参数的特殊转换。它依赖于状态的normalized时间。在Exit Time指定的特定时间进行转换检查 |
Settings | 折叠菜单包含详细的transition设置,如下所示 |
Exit Time | 如果勾选了Has Exit Time,则此值表示transition生效的确切时间.这用normalized时间表示(例如,exit time为0.75表示在第一帧上播放75%的动画时,Exit Time时间条件为真).在下一帧,条件为假。对于循环动画,每个循环都会评估退出时间小于1的transition,因此你可以使用此过程在每个循环的动画中以适当的时间进行transition.如果exit time大于1,则transition仅会评估一次,因此它们可用于在固定数量的循环后的特定时间退出。例如,在3.5个循环之后,评估exit time为3.5的transition |
Fixed Duration | 如果选中Fixed Duration框,则以秒为单位解释transition time.如果未选中Fixed Duration,则transition time将被解释为原状态的normalized时间的一部分 |
Transition Duration | transition的持续时间,使用normalized时间还是秒取决于fixed duration的模式,相对于当前状态的持续时间。这在transition图中可视化为两个蓝色标记之间的部分 |
Transition Offset | 在转换到的目标状态中开始播放的时间偏移量。例如,值0.5表示目标状态在自己的时间轴的50%处开始播放 |
Interruption Source | 使用它来控制可能中断此转换的环境 |
Ordered Interruption | 确定当前转换是否可以被其他转换中断,而与其顺序无关 |
conditions | transition可以具有单个条件,多个条件或根本没有条件。如果你的转换没有条件,Unity Editor只会考虑Exit time,并且在达到Exit time时会发生转换。如果你对transition具有一个或多个条件,则必须满足条件才能触发转换。条件包括-事件参数(条件中考虑的值)。-条件谓词(如果需要,例如'less than(小于)'或'greater than(大于)'浮点数)。-参数值 如果这个转换既勾选了Exit Time并且具有一个或多个条件,需要注意,Unity Editor会在达到Exit time后才考虑条件是否为真,这可以确保你在动画的某个期间发生转换。 |
(2).Transition interruption
使用 Interruption Source和Ordered Interruption可以控制转换的中断条件。
从概念上讲,中断顺序的工作方式就好像transitions已排队,然后解析为从插入的第一个transiton到最后一个transition的有效转换。
(3).Interruption Source property(可查看【Animator- Interruption Source用法】)
Any State的transitions始终首先添加到队列中,然后根据Interruption Source的值,其他transition排队。
Value | Function |
---|---|
None | 不要在添加任何transitions |
Current State | 将transitions从当前状态排队 |
Next State | 将transitons从下个状态排队 |
Current State then Next State | 将转换从当前状态排队,然后将其从下一个状态排队 |
Next State then Current State | 将转换从下一个状态排队,然后从当前状态排队 |
注意,将Interruption Source设置为None,意味着只能通过Any State的transition之一中断转换
(4).Ordered Interruption Property
Ordered Interruption属性会更改队列的解析方式
根据其值,解析队列将在下面列出的不同时刻结束
Value | Ends when |
---|---|
Checked | 已找到有效转换或当前转换 |
Unchecked | 已找到有效转换 |
只有AnyState转换可以自行中断
(5).Transition graph
要手动调整上面列出的设置,你可以直接在字段中输入数字或使用transition图。transition在操作可视元素时修改上述值。
使用以下方式更改图表视图中的transition属性
·拖动Duration "out"标记以更改Transition Duration
·拖动Duration "in"标记以更改Transition Duration和Exit Time
·拖动Target State以调整Transition Offset
·拖动Preview playback current time以在Inspector底部的预览窗口中擦除动画混合。
(6).Blend Tree状态之间的转换
如果属于此转换的当前状态或下一状态是Blend Tree状态,则Blend Tree参数将显示在Inspector中。调整这些值以预览将Blend Tree设置为不同配置时transition的外观。如果你的Blend Tree包含不同长度的剪辑,你应该测试在显示断剪辑和长剪辑时的过渡效果。调整这些值不会影响transition在运行时的行为方式;它们仅用于帮助你预览转换在不同情况下的外观
30.Animation FAQ
(1).一般的问题
Mecanim是什么
Mecanim使我们集成到Unity中的动画软件的名称。在早期的4.x系列的Unity中,它与humanoid角色动画相关联,并且它具有许多特别适合此目的的特征,此时它与旧的(现在遗留的)集成动画系统时分开的。
Mecanim集成了humanoid animation retargeting,muscle control以及state machine system.Mecanim这个名字来自法语单词Mec,意思是Guy。由于Mecanim仅使用humanoid角色进行操作,因此仍然需要我们的传统动画系统来为Unity中的non-humanoid角色和其他基于关键帧的游戏对象动画制作动画。
后来,Unity开发并扩展了Mecanim,将其与动画系统的其余部分集成在一起,以便它可以用于项目中所有的动画。现在Mecanim是Unity的主要动画系统。
Animation组件和Animator组件的区别
Animation组件是传统动画系统中的动画的旧组件。它仍保留在Unity中以实现向后兼容,但你不应将其用于新项目,而应改用最新的Animator组件。
Animation窗口和Animator窗口的区别
Animation窗口允许你在Unity中创建和编辑Animation Clips.你可以使用它为几乎可以在Inspector中编辑的每个属性,如GameObject的position,material的color,light的brightness,sound的volume,甚至是自定义脚本中的任意值制作动画。
Animator窗口允许你将现有的Animation Clip assets组织成一个类似流程图的系统,称为状态机。
这两个窗口都是我们当前动画系统的一部分而不是遗留系统。
也就是说Animation组件是遗留系统的,新项目不应使用。但是Animation窗口是最新的动画系统的一部分
我们正在使用传统动画系统来制作角色动画。现在应该使用当前的动画系统(Mecanim)吗?
一般来说是应该的,Unity的传统动画系统仅用于向后兼容旧项目,与当前的动画系统相比,它的功能集非常有限。你使用旧动画系统的唯一原因是因为旧项目使用了旧的动画系统
(2).Import
为什么导入的mesh上附有Animator组件?
当Unity检测到导入的文件在其时间轴中有动画时,它将在导入时添加Animation组件。你可以在asset的导入设置中通过在Rig选项卡下的"Animation Type"设置为"None"来修改此项。如有必要,你可以一次使用多个文件。
(3).Layer
Layers的排序是否重要?
重要。将按顺序从上到下评估Layers.设置为override的Layer将始终覆盖先前的Layer(如果它们具有mask,则基于mask).
base layer的weight是否应始终设置为0,或者使用另一layer时设置为0?
base layer的weight的值始终为1,override layer将完全覆盖base layer
有没有什么办法从controller获取变量值,不使用string?
你可以使用int来标识states和parameters。使用Animator.StringToHash函数获取整数标识符值。例如:
runState = Animator.StringToHash("Base Layer.Run");
animator.SetBool(runState,false);
如果Sync Layer上的状态与Base Layer中的响应状态相比具有不同的长度会发生什么?
如果layer具有不同的长度,则它们将变得不同步。启用Timing选项以强制当前层根据source layer计算时间。
(4).Avatar Masks
有没有办法创建除LeftFoot,RightFoot,LeftHand,RightHand之外的AvatarIKGoals?
有,还支持knee以及elbow IK
有没有办法定义哪些transforms是Avatar Mask的一部分
有,对于通用剪辑,你可以定义导入的transform动画。对Humanoid clips,始终导入所有human transforms,并且可以定义额外的transforms。
(5).Animations curves
具有曲线的动画如何与不具有曲线的动画混合?
如果你有一个带有曲线的动画和另一个没有曲线的动画,Unity将使用连接到曲线的参数的默认值来进行混合。你可以为参数设置默认值,因此当在具有曲线参数的状态与不具有曲线参数的状态之间进行混合时,它将在曲线值和默认参数值之间进行混合。要为参数设置默认值,只需在Animator Tool窗口中设置其值,而不再LiveLink中。
四、Animation 术语表
1.Animation Clip术语
Term | Definition |
---|---|
Animation Clip | 可用于角色动画或简单动画的动画数据。它可以是一个简单的“单位运动”,例如:“Idle”,“Walk”,或者"Run" |
Animation Curves | 曲线可以附加到Animation Clips,并由游戏中的各种参数控制 |
Avatar Mask | 骨骼中包含或排除的身体部位的规范。用于Animation Layers或者importer中 |
2.Avatar术语
Term | Definition |
---|---|
Avatar | 用于将一个骨骼重新定位到另一个骨骼的界面 |
Retargeting | 将为一个模型创建的动画应用于另一个模型 |
Rigging | 为mesh构建骨骼关节的skeleton hierarchy。使用外部工具执行,例如:Autodesk®3dsMax®或Autodesk®Maya®。 |
Skinning | 将骨骼关节绑定到角色的mesh或者skin的过程。使用外部工具执行,例如:Autodesk®3dsMax®或Autodesk®Maya®。 |
Muscle definition | 这使你可以更直观地控制角色的骨架。当配置Avatar后,Animation系统在muscle空间中工作,这比bone空间更直观 |
T-pose | 角色的手臂伸直到两侧的姿势,形成一个"T"。角色制作Avatar所需姿势 |
Bind-pose | 角色建模的姿势 |
Human template | 预定义的骨骼映射。用于将FBX文件中的骨骼与Avatar匹配 |
Translate DoF | 与选择相关的三个自由度(movement in X,Y&Z) |
3.Animator以及Animator Controller术语
Term | Definition |
---|---|
Animator Component | 模型上的组件,使用Animation系统为该模型设置动画。改组件引用了Animator Controller asset来控制动画 |
Root Motion | 角色根的运动,无论是由动画本身控制还是由外部控制 |
Animator Controller | Animator Controller通过具有Animation State Machines和Animation Blend Trees的Animation Layers控制动画,由Animation Parameters控制。具有Animator组件的多个模型可以引用相同的Animator Controller |
Animator Window | Animator Controller可视化和编辑的窗口。 |
Animator Layer | Animation Layer包含一个Animation State Machine,用于控制模型或其一部分的动画。例如,如果你有一个用于行走或跳跃的全身的Layer,以及一个用于上身运动的更高的Layer,例如:投掷物体或射击。较高的Layer优先于全身的Layer控制身体的部位 |
Animation State Machine | 控制Animation States交互的图形。每个状态都引用Animation Blend Tree或单个Animation Clip |
Animation Blend Tree | 用于基于float的Animation Parameters的相似Animation Clips之间的连续混合 |
Animation Parameters | 用于脚本和Animator Controller之间进行通信。某些参数可以在脚本中设置并由控制器使用,而其他参数基于Animation Clip中的Custom Curves,可以使用脚本API进行采样 |
Inverse Kinematics_(IK)_ | 能够根据世界各种物体控制角色的身体部位 |
五、概念叙述:
IK(反向运动):是使用计算父物体的位移和运动方向,从而将所得信息继承给子物体的一种物理运动方式。以关节连接的物体由一组通过关节连接的刚性片段组成。变换关节的角度可以产生无穷的形状。正向运动问题的解,是给定这些角度时物体的姿势。“逆运动学”问题的难度更高的解是给定物体的姿势时。例如:给定终端效果器(end-effector)的位置时,找到关节的角度。一般情况下,逆运动学问题没有解析解。但是逆运动学可以通过非线性编程技术来解决。特定的特殊运动链–哪些带有球形腕的–运行运动去耦合。这使得我们可以把终端效果器的朝向和位置独立的处理,并导致一个高效的闭形式解。
参考资料:
https://docs.unity3d.com/ScriptReference/Animation.html
https://docs.unity3d.com/Manual/AnimationSection.html
https://blog.csdn.net/noahzuo/article/details/53908141
https://docs.unity3d.com/Manual/animeditor-AnimationEvents.html
https://blog.csdn.net/su9257/article/details/54852529
https://docs.unity3d.com/Manual/AnimatorControllers.html
【Root Motion深度解析】https://blog.csdn.net/cubesky/article/details/39478207
https://docs.unity3d.com/Manual/BlendShapes.html
http://manew.com/thread-108208-1-1.html
http://gad.qq.com/article/detail/37643
http://www.taikr.com/article/502
【Animator- Interruption Source用法】https://zhuanlan.zhihu.com/p/36244526