首页 > 解决方案 > 我需要关于这个 lerping 问题的帮助。我正在尝试制作平台游戏

问题描述

(一旦到达 B 点,它会平稳有序地到达 A 点并返回 B 点)。出于某种原因,平台拒绝移动并保持原状。我已经尝试了很多东西,比如使用vector3.movetowards等等,但没有什么能让它动起来。

这是代码。(A 点和 B 点是不属于平台的空游戏对象)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class MoveTwoTransforms : MonoBehaviour
{

    public Transform pointA;
    public Transform pointB;
    bool HeadingtowardsB;
    bool HeadingtowardsA;
    public float speed = 10;

    // Start is called before the first frame update
    void Start()
    {
        transform.position = pointA.position;
        HeadingtowardsB = true;
        HeadingtowardsA = false;
        GlideAround();

    }

    // Update is called once per frame
    void Update()
    {

    }

    public IEnumerator GlideAround()
    {
        while (true)
        {
            while ((Mathf.Abs((pointB.position.x - transform.position.x) + (pointB.position.y - transform.position.y)) > 0.05f) && HeadingtowardsB == true && HeadingtowardsA==false )
            {
                yield return new WaitForEndOfFrame();
                transform.position = Vector2.Lerp(transform.position, pointB.position, speed * Time.deltaTime);

                if(Mathf.Abs((pointB.position.x - transform.position.x) + (pointB.position.y - transform.position.y)) > 0.05f)
                {

                    HeadingtowardsB = false;
                    HeadingtowardsA = true;
                }

            }
            HeadingtowardsB = false;
            HeadingtowardsA = true;


            while (Mathf.Abs((pointA.position.x - transform.position.x) + (pointA.position.y - transform.position.y)) > 0.05f && HeadingtowardsA==true && HeadingtowardsB==false)
            {
                yield return new WaitForEndOfFrame();
                transform.position=transform.position=Vector3.Lerp(transform.position, pointA.position, speed*Time.deltaTime);
            }
        }
    }
}

没有错误消息,平台不会移动。平台仍在碰撞,它的行为似乎与普通平台一样。

标签: c#unity3d

解决方案


GlideAround()是一个IEnumerator并且不能像方法一样被调用。你必须使用它来启动它StartCoroutine

StartCoroutine(GlideAround());

另请注意,speed * Time.deltaTimeLerp. 在您的情况下,您通常需要一个介于 0-1 之间的常数值(因为您将当前位置重新用作第一个参数)。

例如,0.5 的值意味着:每一帧都将新位置设置为当前位置和目标位置之间的中心。

由于您使用此阈值捕获它0.05f应该没问题,但通常我不会Lerp像这样使用......使用非常小的值,您可能永远不会真正到达目标位置。


因此,我宁愿控制恒定速度并使用

bool isHeadingA = true;

while(true)
{
    // if it was intended you can ofourse also again use
    // Vector2.Distance(transform.position, isHeadingA  ? pointA.position : pointB.position) <= 0.05f)
    while (transform.position != (isHeadingA  ? pointA.position : pointB.position))
    {
        yield return new WaitForEndOfFrame();

        transform.position = Vector2.MoveTowards(transform.position, isHeadingA  ? pointA.position : pointB.position, speed * Time.deltaTime);
    }

    // flip the direction
    isHeadingA = !isHeadingA;
}

!=精度为0.00001并且在这里很好,因为MoveTowards它避免了过冲,所以在某些时候它肯定会到达 if 的位置speed != 0


或者,如果您更愿意使用平滑的进出速度来控制运动的持续时间,您可以使用 Lerp,例如作为因素和缓进和缓出Mathf.PingPongMathf.SmoothStep

while(true)
{
    yield return new WaitForEndOfFrame();

    // linear pingpong between 0 and 1
    var factor = Mathf.PingPong(Time.time, 1);

    // add easing at the ends
    factor = Mathf.SmoothStep(0, 1, factor);
    // optionally add even more easing ;)
    //factor = Mathf.SmoothStep(0, 1, factor);

    transform.position = Vector2.Lerp(pointA.position, pointB.position, factor);
}

推荐阅读