0
\$\begingroup\$

Inside Update :

if (finalLookWeight > 0.95f) // here you can play with a value between 0.95f -> 1.0f
                {
                    if (primaryTarget.interactableMode == InteractableItem.InteractableMode.Action
                        && IsAlreadyThrown == false)
                    {
                        // call your funtion to shoot something here
                        StartCoroutine(ThrowObject(objToThrow.transform, primaryTarget.transform, throwSpeed));
                        IsAlreadyThrown = true;
                    }
                }

I'm using a helper flag IsAlreadyThrown so the Coroutine will not start over and over again nonstop. But I also want to be able from outside this script using in other script to change the flag IsAlreadyThrown back to false at some places/times in the game. How can I make that I can change the flag to false from other scripts ?

And inside the ThrowObject method I did :

IEnumerator ThrowObject(Transform objectToMove, Transform toPosition, float duration)
    {
        float counter = 0;

        while (counter < duration)
        {
            counter += Time.deltaTime;
            Vector3 currentPos = objectToMove.position;

            float time = Vector3.Distance(currentPos, toPosition.position) / (duration - counter) * Time.deltaTime;

            objectToMove.position = Vector3.MoveTowards(currentPos, toPosition.position, time);

            yield return null;
        }

        //StartCoroutine(ThrowBack(objectToMove, toPosition, duration));
    }

And :

IEnumerator ThrowBack(Transform objectToMove, Transform toPosition, float duration)
{
    float counter = 0;

    while (counter < duration)
    {
        counter += Time.deltaTime;
        Vector3 currentPos = objectToMove.position;

        float time = Vector3.Distance(currentPos, toPosition.position) / (duration - counter) * Time.deltaTime;

        objectToMove.position = Vector3.MoveTowards(toPosition.position, currentPos, time);

        yield return null;
    }
}

The first part is working fine the ThrowObject but then I tried to start the second Coroutine ThrowBack but it's just not doing anything. The object is not moving and stay in the target position. It's getting to the line :

objectToMove.position = Vector3.MoveTowards(toPosition.position, currentPos, time);

but the objectToMove just stay in position.

This is what I want to do more or less :

IEnumerator ThrowObject(Transform objectToMove, Transform toPosition, float duration)
    {
        float counter = 0;

        while (counter < duration)
        {
            counter += Time.deltaTime;
            Vector3 currentPos = objectToMove.position;

            float time = Vector3.Distance(currentPos, toPosition.position) / (duration - counter) * Time.deltaTime;

            objectToMove.position = Vector3.MoveTowards(currentPos, toPosition.position, time);

            yield return null;
        }

        DoStuff(objectToMove, toPosition, duration);
    }

    void DoStuff(Transform objectToMove, Transform toPosition, float duration)
    {
        // do things when finish start the ThrowBack

        StartCoroutine(ThrowBack(objectToMove, toPosition, duration));
    }

At least this is the logic I want to do.

\$\endgroup\$
5
  • 1
    \$\begingroup\$ It looks like "objectToMove.position = Vector3.MoveTowards(toPosition.position, currentPos, time);" of ThrowBack has the parameters the wrong way around(currentPos, targetPos) you have (targetPos, currentPos) , does that help anything? I can't see anything wrong with the coroutine itself other than that, can you add the code where you start this second coroutine? When/how is it started? \$\endgroup\$ Commented Oct 24, 2020 at 17:00
  • \$\begingroup\$ @Pheonix2105 The second one start within the first one when the first one end inside ThrowObject at the bottom after the while I'm doing : //StartCoroutine(ThrowBack(objectToMove, toPosition, duration)); I just marked it for now with // ot to use it but this is how I start the second Coroutine using the first one parameters. Since it didn't work I marked it with // but this is how I tried to start the second one. \$\endgroup\$
    – Daniel Lip
    Commented Oct 24, 2020 at 17:13
  • \$\begingroup\$ I see, so you want ThrowBack to Start literally the very instant ThrowObject has finished it's (while) loop? \$\endgroup\$ Commented Oct 24, 2020 at 17:14
  • \$\begingroup\$ @Pheonix2105 When the object reach the target in the first Coroutine after the while then do something and then start throwing the object back you right. So maybe the ThrowBack should start from inside another method that there I want to do some stuff and then when ending doing that stuff then start the ThrowBack. \$\endgroup\$
    – Daniel Lip
    Commented Oct 24, 2020 at 17:17
  • \$\begingroup\$ @Pheonix2105 Updated edited my question with the logic and how I want to do it. \$\endgroup\$
    – Daniel Lip
    Commented Oct 24, 2020 at 17:20

1 Answer 1

1
\$\begingroup\$

So from what I understand, you want a behaviour where, ThrowObject is run until completion, then you wait a specified time and start ThrowBack, for this I would use a third coroutine to control the execution of the first two.

So the idea being you start the Throw Coroutine, which then handles the running of the other two coroutines, with a WaitForSeconds between the calls.

IEnumerator Throw(Transform objectToMove, Transform toPosition, float duration)
{
    //we'll keep hitting ThrowObject every frame until it's while loop is done
    yield return ThrowObject(objectToMove, toPosition, duration);
    //if we're hitting WaitForSeconds then the loop is done, we move onto the next coroutine which is waitforseconds
    yield return new WaitForSeconds(10f);
    //now we're past the wait and back to yielding control to the ThrowBack coroutine
    yield return ThrowBack(objectToMove, toPosition, duration);
    //if we reach here we've finished
    yield break;
}


IEnumerator ThrowBack(Transform objectToMove, Transform toPosition, float duration)
{
    float counter = 0;

    while (counter < duration)
    {
        counter += Time.deltaTime;
        Vector3 currentPos = objectToMove.position;

        float time = Vector3.Distance(currentPos, toPosition.position) / (duration - counter) * Time.deltaTime;

        objectToMove.position = Vector3.MoveTowards(toPosition.position, currentPos, time);

        yield return null;
    }
     yield break;
}

IEnumerator ThrowObject(Transform objectToMove, Transform toPosition, float duration)
{
    float counter = 0;

    while (counter < duration)
    {
        counter += Time.deltaTime;
        Vector3 currentPos = objectToMove.position;

        float time = Vector3.Distance(currentPos, toPosition.position) / (duration - counter) * Time.deltaTime;

        objectToMove.position = Vector3.MoveTowards(currentPos, toPosition.position, time);
        //yield return null essentially means "return here every frame"
        yield return null;
    }
 ///we want these coroutines to end after the while loop now
 yield break;
}

You may need to modify the Throw function to pass both the toPosition variables since each call is likely throwing to a different position.

Using the Throw wrapper to control the flow of the code, can be used in quite a few ways, for example my Spell System uses coroutines to handle a spells logic, you could have the Throw coroutine, wait for a mouse click before throwing back, or as I originally thought you were asking, use a bool (determined by an outside source) to control the logic execution.

IEnumerator Throw(Transform objectToMove, Transform toPosition, float duration)
{
    //we'll keep hitting ThrowObject every frame until it's while loop is done
    yield return ThrowObject(objectToMove, toPosition, duration);



    //if we're hitting WaitForSeconds then the loop is done, we move onto the next coroutine which is waitforseconds
    yield return new WaitForSeconds(10f);

    //Start an infinite while loop
     //or even while(canMove == true) etc
    while (true)
    {
        if (Input.GetMouseButtonDown(0))
        {
            //only fire the coroutine once the mouse is pressed
            yield return ThrowBack(objectToMove, toPosition, duration);
            //once the coroutine is done leave the infinite while loop
            break;
        }
        //make sure we return at the end of the while loop or unity dies
        yield return null;
    }

    //end the entire Throw coroutine
    yield break;
}
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .