协同程序和while循环
我一直在沿着一条路径进行物体移动我从Navmesh Unity3d开始使用我正在使用coroutine,我用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 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"); }
但问题是我必须以恒定速度移动对象,但我的对象在每个循环都获得速度,因为我必须在循环中进行移动,所以它往往会移动直到用户想要通过输入人员来结束它plz帮助我不明白在Coroutines我做错了我的物体的速度正在上升我认为它保持不变但不知何故它没有那样工作谢谢
while (i < 1.0f)
将永远运行,因为i
是0.0f
而且0.0f
总是< 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. }
你的移动function也很糟糕。 下面的function应该做你想做的事情:
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)
作为替代方案,您可以使用Unity的AnimationCurve类轻松地映射出各种超平滑动画类型:
您可以在检查器或代码中定义曲线
public AnimationCurve Linear { get { return new AnimationCurve(new Keyframe(0, 0, 1, 1), new Keyframe(1, 1, 1, 1)); } }
您可以在协程中定义使用情况:
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
也许你可以将速度乘以0.95f。 这将使其加速,然后保持恒定速度,然后当您希望它停止时它将逐渐减速。 增加0.95f将使其加速/减速更快。