【问题标题】:Coroutines and while loop协程和while循环
【发布时间】:2016-07-29 13:47:42
【问题描述】:

我一直在研究沿着我从 Navmesh Unity3d 获得的路径移动的对象 我正在使用协程,我可以在其中使用 while 循环来控制它

  public void DrawPath(NavMeshPath pathParameter, GameObject go)
{

    Debug.Log("path Parameter" + pathParameter.corners.Length);
    if (agent == null || agent.path == null)
    {
        Debug.Log("Returning");
        return;
    }

    line.material = matToApplyOnLineRenderer;
    line.SetWidth(1f, 1f);

    line.SetVertexCount(pathParameter.corners.Length);

    allPoints = new Vector3[pathParameter.corners.Length];

    for (int i = 0; i < pathParameter.corners.Length; i++)
    {
        allPoints[i] = pathParameter.corners[i];
        line.SetPosition(i, pathParameter.corners[i]);

    }

   StartCoroutine(AnimateArrow(pathParameter));

    //StartCoroutine(AnimateArrowHigh(pathParameter));
}


#endregion


#region AnimateArrows


void RunAgain()
{
    StartCoroutine(AnimateArrow(Navpath));
}

IEnumerator AnimateArrow(NavMeshPath path)
{
    Vector3 start;
    Vector3 end;

    while (true)
    {


        if (index > 0)
        {
            if (index != path.corners.Length - 1)
            {
                start = allPoints[index];

                index += 1;
                end = allPoints[index];

                StopCoroutine("MoveObject");
                StartCoroutine(MoveObject(arrow.transform, start, end, 3.0f));
                yield return null;

            }
            else
            {
                index = 0;
                RunAgain();
            }
        }
        else if (index == 0)
        {
            start = allPoints[index];
            arrow.transform.position = allPoints[index];

            index += 1;
            end = allPoints[index];


           StopCoroutine("MoveObject");
           StartCoroutine(MoveObject(arrow.transform, start, end, 3.0f));

            yield return null;
        }
    }


}

IEnumerator MoveObject(Transform arrow, Vector3 startPos, Vector3 endPos, float time)
{
    float i = 0.0f;
    float rate = 1.0f / time;
    journeyLength = Vector3.Distance(startPos, endPos);
            float distCovered = (Time.time - startTime) * speed;
            float fracJourney = distCovered / journeyLength;


    while (i < 1.0f)
    {


       // Debug.Log("fracJourney In While" + fracJourney);
        arrow.position = Vector3.LerpUnclamped(startPos, endPos, fracJourney);

        yield return endPos;
    }
    Debug.LogError("Outside While");
}

但问题是我必须以恒定的速度移动对象,但我的对象在每个循环中都在加速,因为我必须在循环中进行移动,所以它往往会移动,直到用户想要通过输入结束它 伙计们请帮助我不明白我在协程中做错了什么我的对象的速度正在上升我希望它保持不变但不知何故它不能那样工作 谢谢

【问题讨论】:

    标签: c# unity3d while-loop coroutine navmesh


    【解决方案1】:

    作为替代方案,您可以利用 Unity 的 AnimationCurve 类轻松绘制各种超平滑动画类型:

    您可以在检查器或代码中定义曲线

     public AnimationCurve Linear
    {
        get
        {
            return new AnimationCurve(new Keyframe(0, 0, 1, 1), new Keyframe(1, 1, 1, 1));
        }
    }
    

    并且你可以在协程中定义 useage:

    Vector2.Lerp (startPos, targetPos, aCurve.Evaluate(percentCompleted));
    

    “percentCompleted”是您的计时器/TotalTimeToComplete。

    可以从这个函数中看到一个完整的 lerping 示例:

        IEnumerator CoTween(RectTransform aRect, float aTime, Vector2 aDistance, AnimationCurve aCurve, System.Action aCallback = null)
    {
        float startTime = Time.time;
        Vector2 startPos = aRect.anchoredPosition;
        Vector2 targetPos = aRect.anchoredPosition + aDistance;
        float percentCompleted = 0;
        while(Vector2.Distance(aRect.anchoredPosition,targetPos) > .5f && percentCompleted < 1){
            percentCompleted = (Time.time - startTime) / aTime;
            aRect.anchoredPosition = Vector2.Lerp (startPos, targetPos, aCurve.Evaluate(percentCompleted));
            yield return new WaitForEndOfFrame();
            if (aRect == null)
            {
                DeregisterObject(aRect);
                yield break;
            }
        }
        DeregisterObject(aRect);
        mCallbacks.Add(aCallback);
        yield break;
    }
    

    查看此 Tween 库以获取更多代码示例:https://github.com/James9074/Unity-Juice-UI/blob/master/Juice.cs

    【讨论】:

      【解决方案2】:

      while (i &lt; 1.0f) 将永远运行,因为 i0.0f 并且 0.0f 始终是 &lt; 1.0f 并且在您的 while 循环中没有地方可以增加 i 以便它 >= 1.0f .您需要一种退出该 while 循环的方法。它应该如下所示:

      while (i < 1.0f){
      i++ or i= Time.detaTime..... so that this loop will exist at some point.
      }
      

      你的移动功能也很糟糕。下面的函数应该做你想做的事:

      bool isMoving = false;
      IEnumerator MoveObject(Transform arrow, Vector3 startPos, Vector3 endPos, float time = 3)
      {
          //Make sure there is only one instance of this function running
          if (isMoving)
          {
              yield break; ///exit if this is still running
          }
          isMoving = true;
      
          float counter = 0;
          while (counter < time)
          {
              counter += Time.deltaTime;
              arrow.position = Vector3.Lerp(startPos, endPos, counter / time);
              yield return null;
          }
      
          isMoving = false;
      }
      

      另外,在您的 AnimateArrow(NavMeshPath path) 函数中,替换行代码:

      StopCoroutine("MoveObject");
      StartCoroutine(MoveObject(arrow.transform, start, end, 3.0f));
      yield return null;
      

      yield return StartCoroutine(MoveObject(arrow.transform, start, end, 3.0f));
      

      这样做将等待MoveObject 函数完成,然后返回并在while 循环中再次运行。您必须在 if (index != path.corners.Length - 1)else if (index == 0) 中替换这些

      【讨论】:

      • 感谢您的快速响应,但它并没有解决我已经按照您的建议进行操作,但它的运行速度与路径末端的循环速度相同
      • 刚体是否附加到这个游戏对象上?
      • 不,它们不是刚体,甚至不是对撞机,我整天都在搜索谷歌,但没有找到解决方案,我认为这不是正确的方法
      • @Robert,这不是问题所在。当计数器增加时,它所做的只是返回一个更接近结束的新 Vector3。它不会提高速度,也不应该。我已经无数次使用该功能没有问题。
      • @SyedAnwarFahim,试试这几件事:我认为您可能正在从另一个脚本修改值。使用Debug.DrawLine(startPos,endPos,Color.red); 然后转到场景视图。这将绘制一条线并向您展示对象在场景视图中移动到的位置。您可以使用它来确定该位置是否正确。要尝试的另一件事是从AnimateArrow 函数中删除while(true) 语句,看看会发生什么。我不了解您在其他函数中的代码,因此我可能无法再提供帮助,只能尝试这些。
      【解决方案3】:

      也许你可以将速度乘以 0.95f。这将使其加速,然后保持恒定速度,然后当您希望它停止时,它会逐渐减速。增加 0.95f 会使其加速/减速更快。

      【讨论】:

        猜你喜欢
        • 2016-03-12
        • 1970-01-01
        • 2015-06-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-29
        • 1970-01-01
        • 2014-02-01
        相关资源
        最近更新 更多