文章目录
- 问题背景
- 结论先行
- timeline和lerp原理
- 使用timeline+lerp实现相机平滑跟随
- BUG猜想
- 验证和解决
问题背景
今天用timeline+lerp插值做了一个相机平滑跟随的需求
如果只是要求跟随,直接在tick中把相机位置设置成角色位置就可以
但希望有一个相机滞后角色一点点的平滑效果
就可以用timeline+lerp来做
但是做完上述连连看,发现在跟随过程中角色会发生抖动
结论先行
原因是用了timeline的play而不是play from start
区别:
- Play:从上一次调用结束时的位置开始
- Play from Start:从头开始
timeline和lerp原理
timeline的每次play会按照时间输出一个值。可以理解为横轴是时间,纵轴是输出的值。指定完曲线以后,timeline根据当前时间(横轴的值)在纵轴上取出对应的值返回
lerp是插值,根据已知数据点预测中间内容的一种方法。比如:C是已知点A、B中间的一个未知点,C的值可以通过插值计算。最简单的一种插值:
C
=
(
A
+
B
)
÷
2
C=(A+B)\div2
C=(A+B)÷2
UE的浮点插值计算公式是:
C
=
(
1
−
α
)
×
A
+
α
×
B
C=(1-\alpha)\times A+\alpha\times B
C=(1−α)×A+α×B
使用timeline+lerp实现相机平滑跟随
好了,你已经学会timeline和lerp了,现在开始写一个UE 小游戏吧
了解了timeline+lerp的原理我们就知道,lerp需要一个乘在B前面的
α
\alpha
α系数。
按照下图编排,如果设置
α
=
1
\alpha=1
α=1,则
C
=
(
1
−
α
)
×
A
+
α
×
B
=
B
C=(1-\alpha)\times A+\alpha\times B=B
C=(1−α)×A+α×B=B 那么这跟我们直接把相机位置C设置为玩家位置B的效果是一样的
为了实现相机落后角色一点点的跟随感,这里α需要一个(0,1)的值。可以直接粗暴设置为0.5。实现的效果就是:
C
=
(
A
+
B
)
÷
2
C=(A+ B)\div2
C=(A+B)÷2
但直接粗暴0.5设置同样会导致角色抖动。原因是一下子相机移动幅度太大,从左边跳到右边,就导致角色映射到相机上的位置一下在左边一下在右边,体感上就是抖动了
那我们把α设小一点,让相机移动幅度不要太大,是不是就可以了?
答案:是
但是手动设置有如下缺点:
- 需要精细地调整:如果α设小了,不抖动了。但相机移动速度会有点慢。这时候如果角色移动速度很快,相机会跟不上角色。所以具体的值还需要自己调整,直到找到一个看起来不抖动而且移动速度尚可的数值(当然希望精确控制可以直接用lerp)
- 不好维护:如果改动了角色的移动速度,这个α也需要同步调整。当然可以把α设置为一个根据角色移动速度计算出来的值。但这个要怎么计算也需要慢慢试
当然手动设置可以更精确地控制(就是太麻烦了)
所以这里引入定时器+timeline来帮我们控制alpha
BUG猜想
为了节约性能,这里采用了0.03s更新一次,这个间隔比较大,而且使用的timeline引脚是从当前位置开始的Play,α有了一个初值。导致两次调用timeline的时候返回的值差距很大
不均匀且有点大的α就导致了抖动
验证和解决
验证:减小更新间隔,换成每次tick更新一次。不抖动√
解决1:减小更新间隔
解决2:将timeline的驱动引脚换成play from the start
方案1会造成更大的性能开销。故使用方案2√