Jessica
Jessica

Reputation: 27

How to wait for function in script 1 to finish before starting script 2?

In Unity I have GameObjectName which has script 1 and script 2 attached to it. Script1 is an IEnumerator like this.

public IEnumerator Sunglasses()
{
    // Do stuff
}

Script2 looks like this.

public void Start()
{
    Function1();
    String blah = "Things";
    Function2();
    StartCoroutine(Routine2());
    StartCoroutine(Routine3());
}

I need script 1 to finish Sunglasses before script 2 does anything. If I try accessing GameObjectName.Script1 from Script2, Unity says it doesn't exist. How can I make sure that script 1 finishes before starting script 2?

Upvotes: 0

Views: 6048

Answers (2)

Programmer
Programmer

Reputation: 125435

You can add a boolean variable in script one, after the Sunglasses function call is done, set it to true.

Script1:

public bool isDone = false;

public IEnumerator Sunglasses()
{
    // Do stuff

    isDone = true;
}

Script2:

Then in your Script2, you can make your Start function to be a coroutine or IEnumerator instead of a void function. After this, you can wait for isDone to be true every frame.

public bool isDone;
Script1 script1Ref;

public IEnumerator Start()
{
    GameObject s1Obj = GameObject.Find("GameObjectScript1IsAttachedTo");
    script1Ref = s1Obj.GetComponent<Script1>();

    //Wait here until we are done
    while (!script1Ref.isDone)
        yield return null;

    //Done Waiting, now continue with the rest of the code
    Function1();
    String blah = "Things";
    Function2();
    StartCoroutine(Routine2());
    StartCoroutine(Routine3());
}

Finally, if you also need to make sure that Script1 is dine before doing something in the Update function of Script2, just check the isDone variable and return if it it still false.

void Update()
{
    //Return if script 1 is not done
    if (!script1Ref.isDone)
        return;

    //The rest of your code below


}

Note that you want StartCoroutine(Routine3()) to wait until StartCoroutine(Routine2()) is done, you have to yield it.

Replace StartCoroutine(Routine3()) with yield return StartCoroutine(Routine3()).

Upvotes: 2

Tricko
Tricko

Reputation: 551

You can try studying events, or observer pattern. What I have been using is the latter which allows me to add callbacks with a string identifier. For events, you do something like

public static event System.Action onSunglassesCompleted;
public IEnumerator Sunglasses()
{
    //Sunglasses logic here

    //if there is a listener to the event, call it
    if(onSunglassesCompleted != null)
    {
        onSunglassesCompleted();
    }
}

Then on Script2, you just have to add the listener to the event

void Start()
{
    Script1.onSunglassesCompleted += DoThisAfterSunglasses;
}

//This will be called in Script1
void DoThisAfterSunglasses()
{
    //Make sure you do this to avoid memory leaks or missing reference errors once Sprite1 is destroyed
    Script1.onSunglassesCompleted -= DoThisAfterSunglasses;

    Function1();
    String blah = "Things";
    Function2();
    StartCoroutine(Routine2());
    StartCoroutine(Routine3());
}

One thing you can do in events to avoid leaks is by setting it to null after you call it.

if(onSunglassesCompleted != null)
{
    onSunglassesCompleted();
    onSunglassesCompleted = null;
}

Upvotes: 1

Related Questions