请问 Unity max复制动画关键帧帧 怎么复制呢

在Unity3D中控制动画播放
我的图书馆
在Unity3D中控制动画播放
&用Unity3D也算是好久了,但是每次做项目总还是能学到新的东西。这次做一个TPS的项目就遇到了这样一个问题,如何同时在上下半身播放不同的动画?解决方法其实是很简单,但由于对于动画资源的了解不足导致问题不断,最后是彻彻底底的研究了一遍Unity3D的动画系统(Legacy),虽然4.0出了新的动画控制系统,使用了一下功能相比原来确实强大不少,但还是将这次对于原先的动画系统的学习总结记录下来,毕竟这些动画的概念与策略是通用的,而且因为4.0在mac上目前貌似还没有破解所以项目还是得在3.5上做。相信对于深入理解新的动画系统也会很有帮助。
一、Unity3D动画系统相关类
1.1 AnimationClip
AnimationClip是Unity3D中播放动画的最基本对象,通过FBX导入的各个动画对象其实就是一个AnimationClip。这个类已关键帧的形式记录了骨骼关节在各个时间节点上的位置、旋转信息,根据帧频率frameRate结合播放模式wrapMode通过插值计算即可播放出连续的骨骼动画。
1.2 AnimationState
每个AnimationState包含了一个AnimationClip,并记录这个动画片段的一些播放控制属性,实际上是一个AnimationClip的包装器。
其中比较重要的参数有layer,weight, enabled, speed, blendMode这几项。这些参数的具体含义将在自定义混合动画控制中详细解释,在简单的动画控制时并不需要对AnimationState进行直接操作。
1.3 Animation
Animation是Unity3D的动画播放控制组件,包含了一系列的AnimationState对象,提供各种动画播放及控制方法。常用方法有Play(), CrossFade(), Stop()。在脚本中通过animation即可直接引用同一物体上的Animation控件。
二、简单动画播放控制
所谓简单动画播放控制就是同一时间只有一个动作,比如Standard Assets中的那个水管工,静止idle,走walk,跑run,跳跃jump,攻击attack这些动作都是全身动作,同一时间只应该做一种动作,只有在动作切换时需要将两种切换动作进行混合以达到平滑过渡的效果,以上的操作使用Animation提供的CrossFade()方法即可达到。无论是CrossFade还是Play理论上都只需要在切换动画时调用一次即可,当然重复的调用并不会影响动画的播放,当Unity3D检测到当前播放的动画与函数调用使用的动画一样后会忽略该次调用。
三、自定义混合动画控制
3.1 多动画同时播放的需求
在大多数情况下简单的动画播放控制已经足够,然而当游戏变得复杂时,单动画播放带来的问题就是美术工作量的急剧增加。
最为典型的就是第三人称射击(动作)游戏,通常来说游戏中的人物会有各种上身动作如瞄准、射击、换子弹等,而下身则对应站立,行走(通常还是四个方向的行走动作)。这时候如果只能播放一个动作的话就需要美工制作大量的动作(站立瞄准、站立射击、跑步瞄准、跑步射击等等),其工作量可想而知。显然,最为效率的方式是美工分别做出上半身以及下半身的动作,然后由程序根据游戏角色的操作将两者动作混合起来同时播放。而这就涉及到了多动画同时播放的需求。此时简单的CrossFade()方法已经不能满足了,我们需要通过AnimationState来对动画播放进行自定义的控制。
3.2 使用AnimationState控制动画播放
Unity3D的动画播放实际上都是通过AnimationState来进行控制的,Animation组件中提供的CrossFade,Play等方法其实就是将一系列对AnimationState参数进行设置的操作进行了封装。
其中主要相关的参数有四个:
layer: 该动画片段(AnimationClip)所在的播放层次。
weight: 该动画片段在动画混合中所占的权重(0~1)
enable: 该动画片段是否进行播放
blendMode: 混合方式,有两种Blend和Additive
默认初始化情况下Animation组件中的全部AnimationState的layer=0,weight=0, enable=false。Animation组件默认播放的AnimationState的layer=0, weight=1, enable=true。
一、Unity3D动画播放策略
Unity3D在进行动画播放时按照下面的策略进行:
1.找到最高一层的全部AnimationState
2.将其中enable为true且weight & 0的AnimationState中的clip加入混合池(虚构的一个概念)
3.如果当前混合池中全部blendMode为Blend的clip的权重相加少于1,则找到下一层的全部AnimationState。重复2.
4.对混合池中的全部clip进行混合操作,生成最终的动作。
在进行最终混合时所有clip的实际权重会进行归一化处理,即相加为1,处理时根据blendMode的不同结果也会有所差异,下面的例子会进一步说明。
二、使用AnimationState控制播放的实例
举几个实际的例子对Unity3D的动画混合策略进行说明。对于AnimationState的设置全部放在Start或Awake中进行。并且注意把Animation组件中的默认播放动画设为None,取消选中Player Automatically,原因正如前文所述,默认播放的AnimationState参数初始值与其他State不同,会对实验造成影响。
1. 同一层动画的混合播放
AnimationState right= animation[“run_right”];
AnimationState idle= animation[“idle”];
right.layer = 1;right.weight = 1; right.enable =
idle = 1; idle.weight= 1; idle.enable =
&运行结果是角色动画介于行走与静止之间,体现两个动画1:1的混合效果
2. 高层动画覆盖下层动画
&right.layer = 1; right.weight = 1;right.enable =
idle = 0; idle.weight = 1; idle.enable =
&运行结果是角色行走
3. 高层动画与下层动画混合
right.layer = 1; right.weight = 0.5f; right.enable =
idle = 0; idle.weight = 1; idle.enable =
运行结果与1相同,idle的实际weight为1 * (1 - 0.5f)
4. 使用Additive混合不同层动画
right.layer = 1; right.weight = 1; right.enable =
right.blendMode = BlendMode.A
idle = 0; idle.weight = 1; idle.enable =
&运行结果与1相同,idle的实际weight为1/(1+1)
三、其他的动画播放控制参数
speed: 控制动画播放速度,比如调整射击速度就是将该值提高
time: 当前动画所在时间点
warpMode: 动画循环方式,有一次、循环、镜像循环PingPong
3.3 自定义动画过渡
动画过渡实际上就是两种动画混合权重的过渡,前一种动画的权重由1渐变为0,后一种由0变为1,由此实现动画的平滑过渡。在实际操作时,并不需要过渡时在Update()中每帧去调整两种动画AnimationState的权重weight。Animation控件提供了Blend()方法帮助在后台自动计算这种过渡,其使用方法与CrossFade类似,详见Unity3D的script手册。
3.4 Play(), CrossFade()背后的操作
了解这些基本方法背后进行的操作在同时使用AnimationState对动作进行控制时十分有用。
首先是Play(stringanimationName)(Play() = Play(default Animation name))这个方法实际上是将animationName所在层的全部其他AnimationState的weight置为0,enable置为false,将animationName的weight置为1, enable置为true。
CrossFade()与Play()大致相同,只不过他并不直接将其他的AnimationState的weight置为0,而是调用Blend()方法将其向0进行渐变,一旦该AnimationState的weight变为0再将其enable设置为false。
由此可见,当你设置了多层AnimationState后,仅仅调用这两个方法很可能并不能达到你想要的动画控制效果。当然,这两个方法最后有一个默认参数PlayMode来调整执行策略(区别就在于操作对象仅仅在该层还是全部AnimationState对象),总之这一节通过阐述Play与CrossFade背后的操作,希望使我们在使用AnimationState进行混合动画控制编程时能够正确的使用这两个方法以达到期望的效果。
3.5 局部动画
以上所介绍的AnimationState操作只是多动画的手动播放及混合控制,还并没有涉及到如何向开头所讲的上下半身播放不同的动画。要在同一个角色上同时播放两个不同的动作使用局部动画即可。
一、生成局部动画
在Unity3D中有两种方式实现局部动画,一是使用AnimationState的AddMixingTransform方法,该方法传入一个骨骼节点的Transform,调用后该动画片段AnimationClip便只会影响该节点及其子骨骼,而对其他骨骼关节并不再影响。
另一种方法是在动画模型制作时就只对局部的骨骼制作动画,其他骨骼在整个动画片段中都保持不变,这样生成的动画片段AnimationClip中就不会包括对那些不变骨骼的关键帧信息,也就不会对其他骨骼关节进行影响。(这是我根据动画播放的实际控制结果进行的推测,在Unity3D的官方文档中好像并没有直接说明,仍需查证)
了解第二种方法十分重要,虽然还只是推测。因为在与美术沟通前你可能并不知道导入的是一个局部动画,而将其当成全身动画,使得在进行动画混合控制时产生了意想不到的结果。我在一次项目中发现明明角色应该进入idle状态,但是双腿仍然在跑动,为此花了两天时间查证,也是直接促成了这篇文章的诞生,最终发现原来美术给的idle只有上半身有动画,下半身没有,因此虽然idle比跑动高一层,但下半身并不能覆盖。
二、局部动画的混合
局部动画的混合策略与前述Unity3D动画播放策略相同,只不过只是影响局部骨骼。这也就是说,上半身与下半身的动画无论谁所在的层更高,权重多少都不会影响另外半身的动画播放。但是上层的半身动画会覆盖下层的全身动画或与之混合,而全身动画中不包含在半身动画中的骨骼则完全不受影响。
四、射击类游戏应用
参考Unity3.5的官方例子Angry Robot。在这个例子中很好的实现了上下半身的独立旋转,射击动作与跑步动作的半身分离。这一节以此作为样例进行分析。
动作资源:
run_forward,fun_backward, run_left, run_right。四方向的跑动,全身动作,全部置于第1层。
Idle。静止,全身动作,位于第2层。
Attack。攻击,半身动作,位于第4层。混合方式Additive
操作控制:
初始化,全部动作的weight置为1,Attack的enable置为false,其余为true。这样初始状态下Attack不播放,Idle覆盖跑动动作,角色表现为静止站立动作。
移动时将Idle的weight根据速度向0渐变,开放跑动动作。使用CrossFade()在四个跑动动作中选择合适的动作进行播放。停止时再将Idle的weight逐渐置为1,重新覆盖跑动动作。
攻击时将Attack的enable置为true,停止攻击时置为false。由于Attack动作在最高层,且混合模式为Additive,因此站立攻击时Attack动作与行走动作上半身进行混合,跑动攻击时Attack动作与跑动动作上半身进行混合。
转载自: &http://blog.csdn.net/sparrowfc/article/details/8240165
TA的最新馆藏动画视图简介
在创建动画前,需要理解下面的术语:
动画片段:Unity素材会定义一个特定的动画。动画片段定义了简单的光亮动画或者那种七连击的复杂攻击动画。之后你会知道如何集合动画片段来生成更复杂的动画。
曲线:随着时间改变某个属性值能产生一个动画,Unity将这样的动画特性叫做曲线。Unity之所以使用此术语是因为你可以随着时间改变图形的属性值,而图形上的线就在叫做曲线,即使它们是直线,也适用。
键帧:与其设置动画每帧的值,你可以即时在某个点设置值,通过在这些点之间加入值来将Unity填入空隙中。沿曲线明确定义的点就是关键帧,因为它们都是动画里用来计算最终结果的重要的帧。
定义好这些术语后,再来讨论动画视图就简单多了。可以使用下面的窗口来创建特定游戏对象的动画片段。每个片段都包含一个或者多个曲线,每个曲线包含一个或者多个关键帧。
下面的图片强调了动画视图的不同部分,在生成教程中引用区域的名字后便做成列表,每个都有一个简明的描述。
1. 控制栏:此区域包含不同的控制,可以在处理动画片段时候使用。需要的时候再描述吧。
2. 曲线列表:当前动画片段会影响曲线列表,例如添加新属性曲线的列表时。
3. 时间线:一个动画曲线的视图,用来随时间显示它们的值。根据当前视图的模式不同显示的内容也会不同。在Dope Sheet模式下,会包含每个曲线的关键帧,然后随着时间水平布局。此功能跟之前传统动画使用类似,主要用来判断动画中的重要时刻。然而在曲线模式下,时间线会随着动画进行描绘属性的实际值,可视性的提供某个点时时的曲线值。
4. 可视模式按钮:这两个按钮可以用来切换Dope Sheet模式和曲线模式。此教程只使用了Dope Sheet模式,但是每个模式都是有用的。总体来说在Dope Sheet模式下创建关键帧,然后如果需要在关键帧之间加入值的话就切换到曲线模式。
如果上述描述不明确的话也不要担心。此教程中我们会逐步介绍动画视图不同组件的详细情况。
在项目浏览器中,点击zombie_0,然后shift+点击zombie_3,就会生成下面包含所有zombie的列表。
在动画视图中拖拽选择的精灵。如下所示,一个绿色加号图标会出现。
当你看见这个带 + 号的图标出现时,松开你的鼠标。你会看到一个命名为Create New Animation的对话框出现。这个对话框将允许命名你的动画片段,并且还可以为它指定一个保存路径。
在Save As 里面输入 ZombieWalk,并且选择Animations目录,点击保存。下面的图片将展示完成时的对话框。
注意:关键一点是对话框包含这样的内容:&为你的&zombie&游戏对象创建一个新的动画&。
你只能为你场景中的游戏对象创建动画片段(Animation Clips).也就是说,你不能在工程目录(Project View)里面选择一个预制(Prefab),并且为它创建动画。但是你能够为一个实例化的Prefab对象创建动画,这个Prefab对象是你已经添加到Hierarchy上面的对象,Unity会将这些改变(为这样的Prefab实例化对象创建动画)应用到ProjectView上相应的Prefab
& 为Zombie添加一个新的Animator组件,Unity通过这样一个Animatior组件播放一个游戏对象上面的动画片段。你将会在这篇Unity 指南中的下一部分学到更多关于Animator的知识。
& 创建一个叫做 ZombieWalk的动画片段,并且打开 Animation 窗口来编辑它。就像你在下面的图片看到的一样,在这个视图的控制条上的Animation 视图的片段(drop-down)菜单,现在显示ZombieWalk是当前的动画剪辑片段
& 创建一个新的Animator Controller,将它保存在ZombieWalk文件夹中,命名为zombie,你能在zombie的Animator组件上的Controller字段位置看见这个控制器。
这个动画控制器决定了在给定的时刻那一个动画剪辑片段将会播放,关于这一知识点将会在指南的下一部分涉及到。
& 一些用于交互的颜色被呈现出红色。比如,下图中场景的控制条
更多其他红色组件详细信息将会在稍后提及。但是现在我们知道再Unity中,什么时候你会看到一个红色字段或者是UI组件。目前你正在记录一个动画剪辑片段。
在这个Animation 视图中,每次你只能为一个剪辑片段编辑。点击这个编辑片段的drop-down(红色按钮)按钮允许从你指定的游戏对象上选择一个关联的动画剪辑片段进行编辑,正如你在下图中所看到的一样,目前zombie只有一个名为 ZombieWalk的剪辑片段
在上图中,显示出打钩的ZombieWalk为目前选择的剪辑片段,在列表中,当你有多个剪辑片段时,你会发现这个小工具很有用的。上图同时也显示一个命名为Create New Clip的可选菜单项。它允许你创建一个与指定相同的游戏对象关联的动画剪辑片段。当你稍后编辑cat动画时,你将会用它。
下面这个截图显示了怎样拖动精灵到Animation view(动画视图),并且自动的添加一个名为Zombie:Sprite的曲线。
也就是说动画影响了zombie 的SpriteRenderer组件的sprite字段。有时,如果这个属性名字(就是指前面的Sprite field)在这个所附加的对象上的SpriteRenderer组件中没有显示出来,那么这个属性名字也将会包含这个组件的名字。比如:如果你想激活这个SpriteRenderer的Enabled(使能)状态,你将命名为 zombie:SpriteRenderer.enabled.
选择在Hierarchy面板上的zombie(或者选择在Animation view曲线列表单中的zombie:Sprite,这样会自动的选择Hierarchy中的zombie),这时看看Inspector面板上的SpriteRender组件,如下图所示,Sprtie字段是红色的,它不只是显示你正在记录这样一个动画剪辑片段,同时也明确的说明你正在记录的剪辑片段影响该字段
在动画视图的时间轴中,你可以看到在Unity精灵的曲线上添加了四个关键帧。如果你不能看到像下面图像一样清楚的帧,你可以试一下滚动你的鼠标或执行任何滚动操作您的输入设备支持来放大时间轴。
沿着时间轴顶部,你就可以看到由秒数,后面紧跟着冒号(:),和一个帧数的标签。
数值从零开始计算,所以0:02表示第一第二第三帧动画。我想要使用1:02作为一个例子,,但我害怕这个词第三帧第二第二可能会混淆。
正如你所看到的的,Uinty将四个精灵放在0:00,0:01,0:02和0:03。
在做其他事情前,试一下通过点击动画视图的控制条上的Play按钮来运行影片剪辑。
确保动画视图随着场景视图或者游戏视图可见,这样你开可以看到僵尸支撑的东西,或者更准确的说,想被触电一样观察它。
如果这是Unity好动画的想法,你要早点删除那些复活的脚本。幸运的是,这不是Unity的问题。这个问题只是ZombieWalk&s 的配置。
再次点击动画视图的Play按钮停止预览。
注释: 当预览动画影片时,动画视图必须可见。如果你有打开选项卡的布局和你远离它切换到另一个选项卡,动画会立即停止。
你可能会想起本系列的第一部分,僵尸走动以10帧每秒一个周期。如果你看到动画视图控制条的Samples标签,你会看到它设置为60:
Samples 字段表示动画影片剪辑的帧频,它默认是每秒60帧。把这个值改为10,注意时间轴从0:00到0:09在1:00之前:
再次点击动画视图的Play按钮预览动画。你就可以看到僵尸的移动速度更加合理:
僵尸看起来已经好很多,但它自己也没有老。这是因为你定义动画包括第一个周期是四帧,所以但它从zombie_3 跳回 zombie_0.。你需要添加一些帧来使这个过渡自然。
在Project 浏览器中只选择zombie_2 ,把它拖到动画视图里。把光标放在僵尸里面:精灵排列在时间轴,只要放在右边的最后一帧上,设变鼠标,如下所示:
现在你可以看到关键帧数是在0:00到0:04。然而,有你的放大级别决定,很容易不小心把新的关键帧放在靠右比较远的位置。举个例子:
如果发现这种情况,只要简单的使用拖动左边的关键帧上方曲线上的小钻石,如下所以:
现在重复之前的过程添加zombie_1 到动画的最后,也就是放到0:05上。现在你的动画视图看起来就像这样:
按下动画视图的Play按钮测试动画。你的僵尸大摇大摆的走动。
动画音频剪辑完成,运行场景,确保僵尸有生机的移动.
你很成功是使用动画影片剪辑取代僵尸基于脚本动画。这看起来似乎有不少收获,但它依旧需要很多话来形容UI。如果你想打破实际上想做的,你可以简单的拓展一些精灵到动画视图,并且设置一些帧数,现在要踢自己在第一时间上写作。
注释: 如果在场景中还没有僵尸的游戏物体,你可以使用写简单的方法来创建和僵尸动画。
如果你在工程浏览视图中简单的选择一组精灵,然后把它们拖动到场景或者层级视图中,在Uinty中看起来很简单,像创建动画影片,动画师和动画控制器。然而,在场景中创建游戏物体,并连接它的一切。我猜想在Unity5.0中,你将只要拖拽精灵到场景中,Unity将会自动创建正确的基于艺术风格的游戏播放。你将会在这里第一次听到!
好吧,你已经知道很多在Unity中的动画,但仍然有很多要学。幸运的是,你已经有一个完美的猫试验坐在那里了。
原文链接:
建议使用电驴(eMule)下载分享的资源。
说明:本教程来源互联网或网友分享或出版商宣传分享,仅为学习研究或媒体推广,51zixue.net不保证资料的完整性。
上一篇:& 下一篇:
51自学网 我要自学网视频教程,视频下载 自学网 自学编程网 CAD自学网 PS自学网 www.51zixue.netUnity - 通过降低精度减少动画文件的大小-爱编程
Unity - 通过降低精度减少动画文件的大小
Animation是Unity中的动画文件,主要内容由一个个关键帧数据构成。通过将Unity的资源序列化方式调整为Text,就可以以文本方式查看动画文件。通过菜单项Edit -& Project Settings -& Editor打开Editor Settings窗口,就可以设置资源序列化方式:
下图展示了我对一个Cube制作的动画,动画中包含了若干个关键帧,调整了Cube的坐标位置和旋转方向:
以文本方式打开动画文件,部分内容如下:
动画文件的序列化格式不在我们的讨论范围内,本文我们主要讨论的是通过降低精度来减少动画文件的大小。通过查看动画文件,我们发现Unity在序列化动画文件时使用的浮点精度比较高,可以到小数点后面很多位。因此,通过降低精度我们就可以减少动画文件的大小。这里我们使用python脚本来实现该功能,处理的逻辑如下:1. 读取动画文件中的每一行2. 对于读取到的每一行,去除行尾的换行符3. 使用"空格"作为分隔符,分隔行内容4. 对于分隔后的每一个内容,使用正则表达式查询是否包含浮点数据5. 如果包含浮点数据,则使用四舍五入法保留小数点3位。如果不包含浮点数据,则直接写入到输出文件
下面是python代码,可以根据需要自行调整:
animFile = open("Move.anim")
outputFile = open("NewMove.anim", "w", newline='\n')
for l in animFile.readlines():
# 读取文件中的每一行
line = l.rstrip()
# 对于读取到的每一行,去除行尾的换行符
words = line.split(' ')
# 使用"空格"作为分隔符,分隔行内容
for word in words:
match = re.match("-?\d+\.\d+", word)
# 对于分隔后的每一个内容,使用正则表达式查询是否包含浮点数据
# 如果包含浮点数据,则使用四舍五入法保留小数点3位。如果不包含浮点数据,则直接写入到输出文件
value = match.group(0)
floatValue = float(value)
outputFile.write(word.replace(value, str(round(floatValue, 3))))
outputFile.write(word)
if word != words[-1]:
outputFile.write(' ')
outputFile.write('\n')
通过降低精度调整后,动画文件如下:
通过降低精度的调整,我们将大小为19.2KB的动画文件降低到了18.3KB。看上去很微不足道,这是因为这个动画文件仅仅包含了13帧动画数据,对于真实项目中成百上千帧的动画文件,节省量是很客观的。以133秒的动画文件为例,大小从8MB降低到了3MB。
版权所有 爱编程 (C) Copyright 2012. . All Rights Reserved.
闽ICP备号-3
微信扫一扫关注爱编程,每天为您推送一篇经典技术文章。

参考资料

 

随机推荐