0

I have been working on a object movement along a path Which i have been geting from Navmesh Unity3d I am using coroutine in which i controled it with while loop as i can show

  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");
}

But the problem is i have to move object on a constant speed but my object is gaining speed at every loop as i have to make movement in a loop so it tends to move until user wants to end it by input guys plz help i dont understand what i am doing wrong in Coroutines that the speed of my objects is rising i wat it to stay constant but somehow its not working that way thanks

Syed Anwar Fahim
  • 306
  • 5
  • 15

3 Answers3

2

As an alternative, you could utilize Unity's AnimationCurve class to map out all kinds of super smooth animation types easily:

enter image description here

You can define the curves in the inspector, or in code

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

And you can define useage in a coroutine as such:

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

Where "percentCompleted" is your timer/TotalTimeToComplete.

A full example of lerping can be seen from this function:

    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;
}

Check out this Tween library for more code examples: https://github.com/James9074/Unity-Juice-UI/blob/master/Juice.cs

JamesTheMage
  • 82
  • 1
  • 8
1

while (i < 1.0f) will run forever because i is 0.0f and 0.0f is always < 1.0f and there is no place inside your while loop, where you increement i so that it will >= 1.0f. You need a way to exit that while loop. It should have looked like something below:

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

Also your moving function is bad. The function below should do what you are trying to do:

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;
}

Also, in your AnimateArrow(NavMeshPath path) function, replace these three lines of code:

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

with

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

Doing this will wait the MoveObject function to finish before returning and running again in the while loop. You have to replace these inside if (index != path.corners.Length - 1) and else if (index == 0)

Programmer
  • 121,791
  • 22
  • 236
  • 328
  • Thanks for fast response But its not solve i have done what you suggest but its doing the same thing gaining speed as its loops from path's end – Syed Anwar Fahim Apr 08 '16 at 11:31
  • Is rigidbody attached to this gameObject? – Programmer Apr 08 '16 at 12:20
  • No their is no Rigid-body or even a collider I have been searching google all day but haven't found the solution i think it is not a correct approach to do this – Syed Anwar Fahim Apr 08 '16 at 12:43
  • @Robert, That's not the problem. when counter increases, all it does is return a new Vector3 that is closer to end. It does not increase speed and should not. I have been using that function countless of times without problems. – Programmer Apr 08 '16 at 15:52
  • @SyedAnwarFahim,Try these few things: I think that you are probably modifying the value from another script. Use `Debug.DrawLine(startPos,endPos,Color.red);` then go to scene view. This will draw a line and show you how where the object is moving to in the scene view. You can use it to determine if that location correct. Another thing to try is to remove the `while(true)` statement from your `AnimateArrow` function and see what happens. I don't understand your code in your other functions so I may no longer be able to help but try those. – Programmer Apr 08 '16 at 16:02
  • @Programmer I apologize, I was thinking of MoveTowards instead of Lerp :) – Allen Apr 08 '16 at 16:17
0

Maybe you could multiply the velocity by, say, 0.95f. This will make it accelerate, then stay at a constant speed, and then when you want it to stop it will gradually decelerate. Increasing the 0.95f will cause it to accelerate/decelerate faster.

Zac
  • 813
  • 10
  • 22