x


how to call something just once from an update function

Hi,

I have level0 (small) and level1 (large). I have the build set up so level0 loads first. I would then like to load an object (a door) into level0 when level1 had finished loading. I am using the Update() function to determine when level 1 has finished loading, but I find that if I try to instantiate the door from inside the Update() function, I get many many doors. Is there a way to get just one door? Here's the code. Thanks. Zaffer

function Update() { 
if(Application.GetStreamProgressForLevel(levelToLoad) == 1) { 
   Progress.message = "Level at index 1 has been fully streamed!";
   Instantiate(door, Vector3(154, 1.8, 166), Quaternion.identity);
   level1Ready = true; 
}
else {
    percentageLoaded = Application.GetStreamProgressForLevel(levelToLoad) * 100;
    Progress.message = percentageLoaded.ToString();
    level1Ready = false;
}

}

more ▼

asked Jun 19 '12 at 01:48 AM

Zaffer gravatar image

Zaffer
213 12 16 20

Thanks Eric5h5,

Would greatly appreciate it if you would show me how to set up the coroutine. Thanks.

Zaffer

Jun 19 '12 at 02:42 AM Zaffer

Have you read the docs about StartCoroutine and so on?

Jun 19 '12 at 02:54 AM Eric5h5

Thanks for the tip. I will read up on coroutines and try to figure out.

Zaffer

Jun 19 '12 at 03:02 AM Zaffer

Hi Tim and Eric5h5:

Still getting lots of doors. Am I getting warmer? Thanks. Zaffer

function Update() { if(Application.GetStreamProgressForLevel(levelToLoad) == 1) { Progress.message = "Level at index 1 has been fully streamed!"; StartCoroutine(MakeDoor()); level1Ready = true; } else { percentageLoaded = Application.GetStreamProgressForLevel(levelToLoad) * 100; Progress.message = percentageLoaded.ToString(); level1Ready = false; } }

function MakeDoor(){ yield Instantiate(door, Vector3(154, 1.8, 166), Quaternion.identity);

}

Jun 19 '12 at 01:37 PM Zaffer

I think you don't need the Update() function.

I'll write something down here which I think is more like what your coroutine should look like: (sorry it's in C#)

IEnumerator LoadInOrder() { level1Ready = false;

    //Wait while the scene is loading, this while loop will act as a "temporary update" until the scene is fully loaded
    while (Application.GetStreamProgressForLevel(levelToLoad) < 1)
    {
        percentageLoaded = Application.GetStreamProgressForLevel(levelToLoad) * 100;
        Progress.message = percentageLoaded.ToString();
        yield return new WaitForEndOfFrame();
    }

    //Scene was fully loaded
    level1Ready = true;
    Progress.message = "Level at index 1 has been fully streamed!";
    Instantiate(door, Vector3(154, 1.8, 166), Quaternion.identity);
}

You should start this coroutine after you started loading the level. Then, this coroutine will perform the while loop until it is fully loaded, whereafter your door will only be instantiated once.

Hope this is what you want to achieve.

Jun 19 '12 at 02:29 PM Tim Michels
(comments are locked)
10|3000 characters needed characters left

5 answers: sort voted first

You'd be better off not using Update, but rather a coroutine, since the point of Update is that it runs every frame. With a coroutine you can just wait until the event is done and run the code afterward once.

more ▼

answered Jun 19 '12 at 01:52 AM

Eric5h5 gravatar image

Eric5h5
80.3k 42 132 521

(comments are locked)
10|3000 characters needed characters left

Hi,

It took me awhile, but I finally figured out I could do what I wanted with a simple Boolean variable, doorPresent, which I set false in the Start() function. Then I set that to true after making only one door. Seems to be working so far. Coroutines and yield look really interesting -- will study them more. Thanks. Zaffer

function Update() { 
    if(Application.GetStreamProgressForLevel(levelToLoad) == 1) { 
       Progress.message = "Level at index 1 has been fully streamed!";
       //StartCoroutine(MakeDoor()); 
       MakeDoor();
       level1Ready = true; 
    }
    else {
        percentageLoaded = Application.GetStreamProgressForLevel(levelToLoad) * 100;
        Progress.message = percentageLoaded.ToString();
        level1Ready = false;
    }
} 

function MakeDoor(){
    //yield;
    if(doorPresent == false){
        Instantiate(door, Vector3(154, 1.8, 166), Quaternion.identity);
        doorPresent = true;
    }

}
more ▼

answered Jun 19 '12 at 02:30 PM

Zaffer gravatar image

Zaffer
213 12 16 20

Well, this is merely a hack. It will work, but you're better off using the method I just posted.

Greets

Jun 19 '12 at 02:33 PM Tim Michels
(comments are locked)
10|3000 characters needed characters left

Here's an exampe on how to use a coroutine: In this (really simple) example the coroutine gets started in the Start() function.

void Start()
{
    StartCoroutine(DoSomeStuff());
}

IEnumerator DoSomeStuff()
{

    //"Ready" gets logged
    Debug.Log("Ready");

    //Coroutine will wait 1 second to continue
    yield return new WaitForSeconds(1.0f);

    //"Set" gets logged
    Debug.Log("Set");

    //Coroutine will wait 1 second to continue         
    yield return new WaitForSeconds(1.0f);

    //"Go" gets logged
    Debug.log("Go");

    ...
}

You can do anything you like within a coroutine, the "yield" statement simply sets the function on "hold" for how long you choose.

You can also use "yield return new WaitForEndOfFrame()" and other functions. When you get the hang of coroutines, you can do some really cool stuff with it.

Cheers.

more ▼

answered Jun 19 '12 at 08:27 AM

Tim Michels gravatar image

Tim Michels
1.8k 8 16 20

(comments are locked)
10|3000 characters needed characters left

Hi Eric5h5 and Tim,

I wanted to take your advice about coroutines being better, and after some work, I was able to set up a loading sequence using a while loop, yield and coroutines instead Update(). I needed a little help from regular forum, but everything works. Here's the code. Zaffer

P.S. You are right, Tim, couroutines are very cool!

function Start(){ ManageLoadingElements(); }

function ManageLoadingElements(){
    yield StartCoroutine("SetUpLoadingElements");
    TakeDownLoadingElements();
}

function SetUpLoadingElements(){
    while(Application.GetStreamProgressForLevel(levelToLoad) < 1){
        percentageLoaded = Application.GetStreamProgressForLevel(levelToLoad) * 100;
        progressCylinder.transform.localScale.x = percentageLoaded * 0.1;
        progressCylinder.transform.position = progressCylinderPosition;
        progressText3D.text = Mathf.RoundToInt(percentageLoaded) + "%"; 
        yield;
    }
}

function TakeDownLoadingElements(){
    Destroy(progressCylinder);
    Destroy(progressText3D);  
    MakeDoor();
}

function MakeDoor(){
    var door : GameObject;
    if(doorPresent == false){
        door = Instantiate(doorPrefab, Vector3(157, 2.65, 169.59), Quaternion.identity);
        doorPresent = true;
        door.name = "Iron Door";
    }
}
more ▼

answered Jul 03 '12 at 08:24 PM

Zaffer gravatar image

Zaffer
213 12 16 20

(comments are locked)
10|3000 characters needed characters left

I would use a boolean variable, that is true only for the first run.

var firstCall:Boolean;
void Start()
{
    firstCall = true;
}
function Update() { 
    if(Application.GetStreamProgressForLevel(levelToLoad) == 1) { 
       Progress.message = "Level at index 1 has been fully streamed!";
       //StartCoroutine(MakeDoor());
       if(firstCall)
       {
          MakeDoor();
          firstCall = false;
       }
       level1Ready = true; 
    }
    else {
        percentageLoaded = Application.GetStreamProgressForLevel(levelToLoad) * 100;
        Progress.message = percentageLoaded.ToString();
        level1Ready = false;
    }
}
more ▼

answered Jul 03 '12 at 08:34 PM

Luci85 gravatar image

Luci85
143 6 14 16

That's a good strategy too. Thanks.

Jul 03 '12 at 09:48 PM Zaffer

But if you get more than one door, then that means the else branch isn't called as it should be, right?

Jul 03 '12 at 09:51 PM Luci85

I have not actually tried your idea, just thought it looked like a good solution.

Jul 03 '12 at 11:33 PM Zaffer
(comments are locked)
10|3000 characters needed characters left
Your answer
toggle preview:

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this question

By Email:

Once you sign in you will be able to subscribe for any updates here

By RSS:

Answers

Answers and Comments

Topics:

x1675
x496

asked: Jun 19 '12 at 01:48 AM

Seen: 783 times

Last Updated: Jul 03 '12 at 11:33 PM