问题描述
游戏:在一个用 Unity 制作的简单 2D 人像游戏中,我有一个游戏对象(玩家),它有一个固定的位置并且向上移动。相机跟随玩家,动画障碍物不时从左向右移动。附加的 Screenshot 显示了场景。
问题: 运动不流畅,因为播放器似乎在抖动。我想我已经确定了原因之一:Time.deltaTime 的大变化。平均值是 0.0167,但我有变化。最小值为 0.00177,最大值为 0.2249519。
设置: 目标帧率为 60。我使用 Unity 2019.4.2f1,并将 iPhone X 和 iOS 14.2 作为构建目标。
脚本
public class Player: MonoBehaviour
{
float speed = 5f;
void Update()
{
transform.Translate(0,speed*Time.deltaTime,0);
}
}
public class CamFollow : MonoBehaviour
{
public Transform Player;
private Vector3 FollowVector;
void LateUpdate()
{
FollowVector = Player.position - new Vector3(0,-4.0f,10);
transform.position = Vector3.Lerp(transform.position,FollowVector,Time.deltaTime * 4f);
}
}
注意:我需要使用Lerp,因为播放器可能会降低或增加速度一秒钟,然后相机轻轻移动到新位置,然后再换回来。对于障碍,我没有脚本。它们通过使用动画组件移动。对于障碍物,我只循环改变位置的 x 值。
我的替代解决方案:
1.将 Time.deltaTime 的值更改为 0.01666667f 的常量值:
void Update()
{
transform.Translate(0,speed*0.01666667f,0);
}
这使得 Unity Editor 中的 Player Object 抖动很大,但在设备上只有一点点抖动
2.对摄像机跟随和玩家运动使用固定更新
这使得运动和相机跟随完美流畅,但动画对象抖动很多。我知道 Unity 希望在下一次更新之一中解决 deltaTime 问题。但是我的问题应该有解决方案,所以有人有类似的问题,可以解决吗?我更喜欢第二种选择,因为运动看起来非常流畅和漂亮,所以我可以以某种方式制作“fixedUpdate”的动画部分吗?
解决方法
“deltaTime”的变化是可以预料的。
PC 上的差异很大,因为您在一台复杂的计算机上运行,该计算机具有复杂的操作系统和许多同时运行的其他应用程序,每个应用程序都有多个线程,每隔一段时间就想做一些工作。因此,操作系统的调度程序无法保证您将在所需的精确时刻获得时间片,以便渲染下一帧。
移动设备上的变化更小,因为它是一个更简单的机器,运行更少,因此调度程序能够为您提供接近您要求的精确间隔的时间片。
当您这样做时,您已经考虑到了这种变化
transform.Translate( 0,speed * Time.deltaTime,0 );
这是游戏开发中的一项基本技术:帧速率永远不会恒定,因此您必须在每一帧上移动对象的距离取决于此帧与前一帧之间经过的精确时间量。
>所以,那部分很好。
你的问题在于
transform.position = Vector3.Lerp( transform.position,FollowVector,Time.deltaTime * 4f );
在这里,您为 Time.deltaTime * 4f
的参数 t
传递 Vector3.Lerp()
。我不知道您要完成什么,但是您需要传递的数字需要在 0 和 1 之间逐渐过渡,而您传递的是随机变化的秒数乘以某个魔法常数 {{1} }.这看起来不正确。
我能想到的几个选项:
- 始终将
4
用于0.5
,以便相机始终冲向正确的位置,然后在靠近时减速。 - 为摄像机计算单独的速度向量,然后使用平移移动摄像机,就像对玩家所做的一样。