由于Time.deltaTime,C#/Unity相机跟随抖动 [英] C#/Unity Camera Follow Jitter due to Time.deltaTime

查看:215
本文介绍了由于Time.deltaTime,C#/Unity相机跟随抖动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

游戏:在Unity中制作的简单2D人像游戏中,我有一个GameObject(玩家),它的位置固定并且向上移动.相机会跟随播放器,并且动画障碍物会不时地从左向右移动.随附的屏幕截图显示了场景.

Game: In a simple 2D Portrait Game made in Unity, I have a GameObject (Player) that has a fixed location and which is moving upwards. The Camera follows the Player and animated Obstacles are spawning from time to time moving left to right. The attached Screenshot shows the Scene.

问题:运动似乎不平稳,因为播放器似乎在抖动.我想我已经确定了原因之一:Time.deltaTime的较大差异.平均值是0.0167,但是我有差异.最小值为0.00177,最大值为0.2249519.

The Problem: The Movement is not smooth, as it seems like the Player is jittering. I think I already identified one of the causes: Big variation of Time.deltaTime. Average value is 0.0167, but I had variations. Minimum was 0.00177, maximum value was 0.2249519.

设置:目标帧率为60.我使用Unity 2019.4.2f1,并使用iOS 14.2作为构建目标的iPhone X.

Settings: Target Framerate is 60. I use Unity 2019.4.2f1 and as build target an iPhone X with 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值.

Note: I need to use Lerp, because the Player may lower or increase the speed for one second, then the camera gently moves to the new position, before changing back. For the Obstacles I don't have a Script. They are moving, by using the Animation Component. For the Obstacles I only loop a change of the x value of the position.

我的替代解决方案:

1.将Time.deltaTime的值更改为恒定值0.01666667f:

void Update() 
{ 
    transform.Translate(0,speed*0.01666667f,0); 
} 

这会使Player对象在Unity Editor中产生很大的抖动,而在设备上仅产生少量抖动

This makes the Player Object jitter a lot in the Unity Editor but only a little on the device

2.对摄像机跟随和玩家移动都使用固定更新

这可以使运动和摄影机完全顺畅地运动,但动画对象会抖动很多.我知道Unity希望在下一个更新中解决deltaTime问题.但是我的问题应该有解决方案,那么有人有类似的问题可以解决吗?我更喜欢第二种选择,因为该运动看起来确实非常流畅且美观,所以我能以某种方式使动画成为"fixedUpdate"的一部分吗?

This makes the movement and camera follow perfectly smooth, but the animated objects jitter a lot. I know Unity wants to adress the deltaTime issue in one of the next updates. But there should be a solution for my problem, so did anybody have a similiar problem, which could be solved? I prefer the 2nd alternative, because the movement looked really smooth and nice, so can I somehow make the animation part of "fixedUpdate"?

推荐答案

"deltaTime"的变化是可以预期的.

The variation in the 'deltaTime' is to be expected.

PC上的差异很大,因为您是在运行复杂操作系统的复杂计算机上运行的,同时还要运行许多其他应用程序,每个应用程序都具有多个线程,而每时每刻都需要做一些工作.因此,操作系统的调度程序无法保证您将在想要的准确时刻获取时间片以渲染下一帧.

The variation is large on the PC because you are running on a complex computer with a complex operating system and lots of other applications running simultaneously, each with a multitude of threads, which every once in a while want to do some work. Thus, the scheduler of the operating system cannot guarantee that you are going to get a time slice at the precise moment that you want it in order to render your next frame.

移动设备上的差异较小,因为它是一台简单得多的机器,运行情况更少,因此调度程序能够为您提供接近您要求的精确时间间隔的时间片.

The variation is smaller on the mobile device because it is a much simpler machine with a lot less going on, so the scheduler is able to give you time slices close to the precise intervals that you are asking.

当您这样做时,您已经考虑到了这种变化

You are already taking this variation into account when you do

transform.Translate( 0, speed * Time.deltaTime, 0 ); 

这是游戏开发中的一项基本技术:帧速率永远不会恒定,因此在每个帧上移动对象的距离取决于该帧与前一帧之间经过的精确时间.

This is a fundamental technique in game development: the frame rate is never constant, so the distance by which you must move an object on each frame depends on the precise amount of time elapsed between this frame and the previous frame.

所以,那部分很好.

您的问题出在

transform.position = Vector3.Lerp( transform.position, FollowVector, Time.deltaTime * 4f );

此处您要为Vector3.Lerp()的参数 t 传递 Time.deltaTime * 4f .我不知道您要完成什么,但是您需要传递的数字需要在0和1之间逐渐过渡,而您传递的是随机变化的秒数乘以一些魔术常数 4.这看起来不正确.

Here you are passing Time.deltaTime * 4f for parameter t of Vector3.Lerp(). I have no idea what you are trying to accomplish, but the number you need to pass there needs to be a gradual transition between 0 and 1, and instead you are passing a randomly varying number of seconds multiplied by some magic constant 4. This does not look correct.

我可以想到的两个选择:

A couple of options that I can think of:

  • 对于 t ,始终使用 0.5 ,这样相机始终会冲到正确的位置,然后在靠近相机时放慢速度.
  • 为摄像头计算一个单独的速度矢量,然后像平移播放器一样使用平移移动摄像头.
  • Always use 0.5 for t so that the camera always rushes to the right position and then slows down as it gets closer to it.
  • Calculate a separate speed vector for the camera, then move the camera using a translation just as you do for the player.

这篇关于由于Time.deltaTime,C#/Unity相机跟随抖动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆