Unity Viewbob 使用 lerp 随机回弹 1 帧

Posted

技术标签:

【中文标题】Unity Viewbob 使用 lerp 随机回弹 1 帧【英文标题】:Unity Viewbob using lerp snaps back for 1 frame at random 【发布时间】:2021-06-16 07:54:18 【问题描述】:

我的 ViewBobScript 有问题,它会弹回 lerps 开始位置 1 帧。

这是我的问题的娱乐/视频: (由于视频的帧率与游戏不匹配,它可能看起来好像 lerp 不流畅,但实际上是。问题是视频开头和结尾处的快照,并且似乎以不规则的间隔发生)

https://youtu.be/UOz2pQcMFjY

这是我的代码:

private float aTimer;
private int viewBobPath = 1;
private float startViewBob;
private float viewBobPathTimer;

private void ViewBob()

    startViewBob = viewBobSpeed / 2;

    aTimer += Time.deltaTime;
    viewBobPathTimer += Time.deltaTime; 

    if (aTimer > startViewBob * viewBobPath)  viewBobPath++; 
    if (viewBobPathTimer > startViewBob)  viewBobPathTimer = 0;  

    if (aTimer < (viewBobSpeed * 2))
    
        switch (viewBobPath)
        
            case 1:
                playerCam.transform.localPosition = Vector3.Lerp(new Vector3(-viewBobHorizontal / 2, 0, 0), new Vector3(0, -viewBobVertical, 0), viewBobPathTimer);
                break;
            case 2:
                playerCam.transform.localPosition = Vector3.Lerp(new Vector3(0, -viewBobVertical, 0), new Vector3(viewBobHorizontal / 2, 0, 0), viewBobPathTimer);
                break;
            case 3:
                playerCam.transform.localPosition = Vector3.Lerp(new Vector3(viewBobHorizontal / 2, 0, 0), new Vector3(0, -viewBobVertical, 0), viewBobPathTimer);
                break;
            case 4:
                playerCam.transform.localPosition = Vector3.Lerp(new Vector3(0, -viewBobVertical, 0), new Vector3(-viewBobHorizontal / 2, 0, 0), viewBobPathTimer);
                break;
        
    
    else  aTimer = 0; viewBobPathTimer = 0; viewBobPath = 1; 


另外,我知道统一角色控制器有 ViewBobbing。但这不是我的应用程序的选项。

非常感谢您的帮助!

编辑:这是从更新函数中调用的,虽然我尝试过Fixed和late update都不会改变,解决或减少问题。

虽然我的脚本可以运行并且我正在继续我的项目,但如果您知道我上面的代码为什么不起作用/是否完成了 Snap,我将不胜感激,因此我会从中学习!

【问题讨论】:

【参考方案1】:

我会采取不同的方法,将Time.deltaTime 添加到一个字段,然后计算该字段对应的路径和t 参数。 Mathf.Repeat 对此很有用。

[SerializeField] int pathIndex;
[SerializeField] float pathT;
[SerializeField] float aTimer;

[SerializeField] float pathDuration = 1f; // how long each path takes in seconds

private void ViewBob()

    // update aTimer but wrap around at pathDuration x 4 ( [0, 4pD) )
    aTimer = Mathf.Repeat(aTimer + Time.deltaTime, pathDuration * 4f);

    // How many path durations is aTimer along? ( 0, 1, 2, 3 )
    pathIndex = Mathf.FloorToInt(aTimer/pathDuration);

    // How far into the current path duration is aTimer?  ( [0,1) )
    pathT = Mathf.Repeat(aTimer, pathDuration) / pathDuration;

    Vector3 fromVector;
    Vector3 toVector;

    // assign to/from vectors based on pathIndex
    switch (pathIndex)
    
        default:
        case 0:
            fromVector = new Vector3(-viewBobHorizontal / 2, 0, 0);
            toVector = new Vector3(0, -viewBobVertical, 0);
            break;
        case 1:
            fromVector = new Vector3(0, -viewBobVertical, 0);
            toVector = new Vector3(viewBobHorizontal / 2, 0, 0);
            break;
        case 2:
            fromVector = new Vector3(viewBobHorizontal / 2, 0, 0);
            toVector = new Vector3(0, -viewBobVertical, 0);
            break;
        case 3:
            fromVector = new Vector3(0, -viewBobVertical, 0);
            toVector = new Vector3(-viewBobHorizontal / 2, 0, 0);
            break;
    

    // lerp position based on pathT and the to/from vectors
    playerCam.transform.localPosition = Vector3.Lerp(fromVector, toVector, pathT);

【讨论】:

谢谢@Ruzihm,这工作完美无缺!并以我完全理解您是如何做到的方式编写的。 + 了解了 Matf 的便利性。重复是 xD

以上是关于Unity Viewbob 使用 lerp 随机回弹 1 帧的主要内容,如果未能解决你的问题,请参考以下文章

如何正确的使用Lerp In Unity

Unity - 使用 foreach 循环以及父对象和子对象进行 Lerp 旋转?

unity的color.lerp怎么用

Unity物体移动的几种方式与表现(Lerp,SmoothDamp,MoveTowards的区别)

unity 怎么sprite一直在屏幕范围内移动

Unity云消散巩固step,lerp和smoothstep