为什么我的对象不停止继续transform.Translate?

时间:2019-06-03 13:51:11

标签: c# unity3d

我希望一个对象在每次变换中移动另一个对象。进行翻译,但是当它到达目的地时它不会停止移动。

我在脚本中尝试了几种方法,但是我不知道可能是什么问题。一件事是:我的代码中有几种方法,这些方法使某些事情在不同的段落中发生不同的移动。因此,我编写了一个小方法,该方法在Input.GetKey()上执行特定的方法,以查看是否在不执行其他任何方法时是否相同,此外,我还注释了Update中调用的所有内容以确保确定。没有其他移动方法可以影响对象。因此,我将只发布在Update中的GetKey上调用的受影响的方法。

“ transPointFirst”到“ transPointFourth”是在检查器中传递的空gameObject。我还检查了TransPoints是否在运行时移动,但是没有,每帧相同的位置。

private void ElevateCaptain()
{
    targetRigid.isKinematic = true;

    var transFirst = new Vector3(transPointFirst.localPosition.x, transPointFirst.localPosition.y, 0);
    var transSecond = new Vector3(transPointSecond.localPosition.x, transPointSecond.localPosition.y, 0);
    var transThird = new Vector3(transPointThird.localPosition.x, transPointThird.localPosition.y, 0);
    var transFourth = new Vector3(transPointFourth.localPosition.x, transPointFourth.localPosition.y, 0);

    target.transform.Translate(transFirst * Time.deltaTime, Space.World);

    if (target.transform.position == transFirst)
        target.transform.Translate(transSecond * Time.deltaTime, Space.World);

    else if (target.transform.position == transSecond)
        target.transform.Translate(transThird * Time.deltaTime, Space.World);

    else if (target.transform.position == transThird)
        target.transform.Translate(transFourth * Time.deltaTime, Space.World);

    else if (target.transform.position == transFourth)
    {
        targetRigid.isKinematic = false;
    }
}

因此,我希望我的目标移至第一个翻译,如果已达到,则移至第二个翻译,依此类推。事实是:目标朝正确的方向移动,但永不停止。不管代码是这样执行的,还是我在第一个transform.Translate调用之后都忽略了所有内容,都没有关系。对象移动到该第一点,并越来越远...当我选择这些点中的另一个作为第一平移时,也是如此。我希望有人能帮助我。

1 个答案:

答案 0 :(得分:0)

这里有很多事情。

如果您的transPointFirsttransPointSecond等具有任何父游戏对象,则将其localPositionposition的{​​{1}}进行比较可能会产生意外的行为。最好直接比较它们的target字段。另外,如果其位置的Z分量已经为position,则无需创建它们的重复0

Vector3期望方向矢量乘以距离,但您给出的似乎是位置矢量。您可能想使用Vector3.MoveTowards计算每帧Translate的位置。您需要一个变量来设置您要移动的速度,理想情况下,它是一个公共区域,因此您可以在检查器中进行设置。

此外,正如Eddge所说,您在每种情况下都首先进行target,这违反了您想要的逻辑。

但是,在Unity中,Translate的{​​{1}}和Vector3运算符已经检查了近似相等性,因此您可以在其中进行操作。

您还需要考虑当对象位于两个位置之间时在帧上会发生什么。如果在应该移动的每一帧上调用==,则可以检查其当前位置是否位于每个连续的点对之间,或者可以使用一些变量来跟踪其“触摸过的点” “ 至今。

一种更简单的写方法是使用Coroutines,然后在您希望它开始移动时只调用一次!=。以下是这些更改和使用协程的代码示例:

ElevateCaptain

如果您决定走ElevateCaptain路线,则当目标要开始移动时,尽管其中包含{ {1}}变量应防止在它已经发生时被调用。

协程或其他方式,对此的一种改进可能是使用public float elevateSpeed; private bool captainElevating; Start() { // ... captainElevating = false; // ... } private void ElevateCaptain() { if (!captainElevating) { captainElevating = true; StartCoroutine("ElevateCaptainCoroutine"); } } private IEnumerator ElevateCaptainCoroutine() { targetRigid.isKinematic = true while (target.transform.position != transPointFirst.position) { target.transform.position = Vector3.MoveTowards( target.transform.position, transPointFirst.position, elevateSpeed * Time.deltaTime); yield return null; } while (target.transform.position != transPointSecond.position) { target.transform.position = Vector3.MoveTowards( target.transform.position, transPointSecond.position, elevateSpeed * Time.deltaTime); yield return null; } while (target.transform.position != transPointThird.position) { target.transform.position = Vector3.MoveTowards( target.transform.position, transPointThird.position, elevateSpeed * Time.deltaTime); yield return null; } while (target.transform.position != transPointFourth.position) { target.transform.position = Vector3.MoveTowards( target.transform.position, transPointFourth.position, elevateSpeed * Time.deltaTime); yield return null; } targetRigid.isKinematic = false; captainElevating = false; } 中的Coroutine并使列表中的Coroutine循环依次将ElevateCaptain移向每个。这样,在检查器中,您可以将任意数量的captainElevating游戏对象拖到列表中,并非常容易地对其进行更改。协程方法的重复结构非常适合这种循环。