在上一篇笔记中(Unity Animation -- Overview_亦枫Leonlew的博客-CSDN博客),我们制作了简单的小球弹跳的动画,但这个动画看起来很不自然,小球的弹跳看起来就像是不受重力影响的物体,没有加速度的影响。要让小球的弹跳动画看起来更自然(不使用物理引擎,只使用动画),我们需要对中间帧进行调整,在Unity中,这是通过曲线编辑器(Curve Editor)来实现的。前面笔记中所用使用的Animation编辑器的一个部分叫做Dopesheet,它主要是关键帧被设置的地方。
下面我们来看看Curve编辑器的使用:
1. 在场景中选择小球对应的游戏物体,在Animation Editor中选择Ball_Bounce动画。然后在Animation编辑器的下方,点击Curves打开曲线编辑器。
2. 使用鼠标滚轮或按F键进行缩小,直到我们看到了所有三个关键帧以及连接关键帧的曲线
在编辑器中显示的曲线是关键帧之间的中间帧的可视化地表现,特别是它们的变化速度非常直观。如果此时预览动画,我们可以在过程中看到这个关系。在动画开始的前几帧,小球缓慢地降低,在中间加速掉落,然后在最后落地的时候变慢了一点。这种类型的变换被称为easing。我们下面来看看不使用easing时是什么情况。
3. 右键点击第一个关键帧,然后在列表中选择Right Tangent -> Linear;
右键点击中间的关键帧,然后在列表中选择Left Tangent -> Linear
这样选择后,第一个关键帧和中间的关键帧之间的曲线会变成一条直线
我们此时再点击Play按钮预览一下动画,注意观察一下和easing方式的区别(下落过程和弹回过程)
1. 右键点击第一个关键帧,选择Camped Auto重置tangent到原始状态
2. 右键点击中间的关键帧,选择Right Tangent -> Linear
3. 在Animation编辑器中点击Play(三角)按钮预览一下
现在这个动画看起来似乎更真实一点了
4. 选择最后一个关键帧,我们可以看到有一个灰色的小的圆柄(handle),这个叫做切线handle(tangent handle)。
5. 拖动这个handle,调整曲线让曲线的顶端更加圆滑一点。
6. 预览并不断调整tangent handle,让小球的弹跳看起来更加真实,弹回来的时候,让动画看起来好像小球在空中停住了一会儿。
7.右键点击中间的关键帧,选择Both Tangents -> Free,这样我们可以对这一帧的左右两侧的切线都进行自由地控制,我们将整体曲线调整成类似V字形的样子
当物体以足够大的力碰到某个表面时,物体或者这个表面会发生形变。当撞击的能量被释放后,变形的物体会恢复到原来的形状(尽可能地接近原始形状)。在动画中,这个过程被封装成了称为squash(挤压)和stretch(拉伸)的技术中。
先来创建挤压:
1. 在Animation编辑器中,将Playehead放到第一个关键帧位置(0:00),打开关键帧记录功能(record按钮按下)
2. 将Playhead移动到第二个关键帧,这个帧是小球触碰地面的帧。调整小球的Scale属性(按R键或者调整Inspector里的Scale属性,或者直接在动画编辑器中编辑这个关键帧的Scale属性),将Scale的Y调整为0.8
3. 移动小球,让小球看起来和地面刚刚接触
如果此时我们通过拖动Playhead,则我们可以手动地预览动画。这个过程称为scrubbing。我们从头拖到尾,可以发现小球现在是有挤压效果,但从动画一开始小球就在慢慢地被挤压(小球还未接触到地面之前也在变扁)。这不是我们想要得到的效果。
4. 将Playehead移动到第一个关键帧(0:00处),选择Scale属性对应的菱形点,然后通过Ctrl+C(MAC系统上Command+C)复制一下这个关键帧。
5. 将Playhead移动到小球刚刚接触地面之前的前一帧,然后Ctrl+V(MAC系统上Command+V)粘贴这个关键帧。
完成了挤压动画关键帧之后,接下来我们实现拉伸的关键帧。对于一个橡胶小球来说,当小球回弹时,会出现被拉伸的形状。
1. 将Playhead移动到小球接触地面后的紧接着的下一帧位置,将Scale的Y调整到1.2
2. 预览并跳帧调整一下挤压和拉伸的关键帧,达到满意效果后关闭Recording功能
现在我们完成了小球弹跳的动画,但如果我们将小球初始位置移动到场景中的另一个位置时,会发生什么事情呢?我们想要达到的效果是小球的起始位置在新的地方,然后正常掉落并播放弹跳动画。但实际上并非如此。
我们将小球移动到另一个位置,然后点击Animaiton编辑器的预览按钮(三角形)
可以看到,动画播放时,小球立刻就回到了最初动画被创建时小球的原始位置上。这是因为关键帧里记录的信息是原始的信息。我们在Inspector中看到的Transfor Position的设置,是和3D空间里被选择物体的位置相关的(世界坐标)。这就麻烦了,我们好不容易制作了一个动画,但是这个动画只能在特定位置才能播放,这样很不灵活。幸运的是,有一种很简单的方法来解决这个问题。
1. 我们撤销一下小球位置的改动,让小球回到原始位置,按Ctrl(Command) + Z
2. 在Hierarchy窗口中,右键创建一个空游戏物体(Create Empty),重命名为BallParent
3. 选择BallParent,在其Inspector属性中,Transform部分选择Reset,将其位置重置为(0,0,0)
4. 将Ball拖动到BallParent游戏物体下方,让它成为BallParent的子物体
5. 移动BallParent到场景中的另一个位置,然后在Animation编辑器中预览一下动画,现在小球可以在任意位置上进行弹跳动画播放了。
我们选择Ball游戏物体,在Inspector中可以看到,小球的位置其实没有发生任何变化。但在Unity中,如果一个物体变成了另一个物体的子物体,它的transform值从世界空间变化为了局部空间(from global to local)。也就是说Ball现在transform里的位置信息,是相对于BallParent位置而言的。我们移动了BallParent游戏物体,并不会影响Ball本身动画里关键帧里的位置。
现实生活中,小球弹跳的样子是,第一次落地,回弹的距离最大,但也不会回到初始位置。随后的多次弹跳中,每一次回弹的距离会逐渐变小。接下来请自行实现一下这个效果。