Search Unity

Accessing Global Functions - unexpected values

Discussion in 'Scripting' started by agentcooper, Mar 31, 2008.

  1. agentcooper

    agentcooper

    Joined:
    Jan 19, 2008
    Posts:
    98
    Hi guys,

    I have a script in place that is a kind of configuration script, setting lots of global variables within the Start() using set() methods. There are also, as you would expect, get() methods that I would like to access from a few other scripts.

    I have created an empty gameObject and attached that to the script. In the second script (the one I am accessing things from), I have the following in place:


    Code (csharp):
    1. var myConfig : GameObject;
    2.  
    3. function Start() {
    4.     var myScript = myConfig.GetComponent(config);
    5.    
    6.     var test = myScript.getTime();
    7.    
    8.     Debug.Log(test);
    9. }
    10.  
    11.  
    I this runs ok but returns returns 0 every time. But if I call the getMethod from within the Start() method of the config script instead, it returns the correct value.

    The code from the config script will is as follows:


    Code (csharp):
    1. //create some public variables to hold the time, weather code and weather type
    2. //set to public to enable access from other scripts
    3. static var globalTime : int;
    4. static var globalWeatherCode : int;
    5. static var globalWeatherType : String;
    6.  
    7. function Start(){
    8.         //get the weather and time index's set them to variables
    9.     setWeatherType(weatherArray[1]);
    10.     setWeatherCode(weatherArray[2]);
    11.     setTime(parseInt(timeArray[0]));
    12. }
    13.  
    14.  
    15.  
    As i said, all the sets and gets work, but only from within the config script. Has it got something to do with the order the functions are called in?
     
  2. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Looks like it; you probably want to use Awake() to make sure the initialization happens first, since any functions with the same name (like Start) can be called in any order; the wrong one in this case.

    --Eric
     
  3. agentcooper

    agentcooper

    Joined:
    Jan 19, 2008
    Posts:
    98
    Hmmm...

    I have changed the function to Awake() instead of Start() and have had to modify the code slightly as the yield call cannot be made within Awak apparently, but still no luck it seems. I think the problem now however is how to keep checking the status of the WWW call.

    I now have a awake / load functions that look like this:



    Code (csharp):
    1.  
    2. function Awake(){
    3.    
    4.     //set the feed for the weather feed
    5.     var weatherURL = basePath + weatherScript;
    6.    
    7.     //set the URL for retreiving the time
    8.     var timeURL = basePath + timeScript;
    9.    
    10.     //all these variables need to be called here and not in CheckWeather as was the original version.
    11.     //This is because Unity throws an error due to the fact that you cannot create instances of objects
    12.     //within functions (with the exception of Start() and Update()
    13.     var weatherData : WWW = new WWW(weatherURL);
    14.    
    15.     var timeData : WWW = new WWW(timeURL);
    16.    
    17.     load(weatherData,timeData);
    18.    
    19. }
    20.  
    21. function load(w : WWW, t : WWW){
    22.    
    23.     //check to see if the downloads have completed
    24.     if(w.isDone  t.isDone){
    25.         //assign the data returned from the weatherFeed request
    26.         var weatherString : String = w.data;
    27.    
    28.         //assign the data returned from the timeURLRequest
    29.         var timeString : String = t.data;
    30.    
    31.         //Get the array values from the CheckWeather function and assign them to a global array
    32.         var weatherArray = CheckWeather(weatherString);
    33.         //Get the array values from the checkTime function and assign them to a global array
    34.         var timeArray = getServerTime(timeString);
    35.    
    36.         //get the weather and time index's set them to variables
    37.         setWeatherType(weatherArray[1]);
    38.         setWeatherCode(weatherArray[2]);
    39.         setTime(parseInt(timeArray[0]));
    40.        
    41.         Debug.Log("config: "+getTime());
    42.     }
    43. }
    44.  
    but correct me if i am wrong, the awake call is only called once so how can i get it to keep checking the isDone status until the data has downloaded?
     
  4. agentcooper

    agentcooper

    Joined:
    Jan 19, 2008
    Posts:
    98
    ok as an update I have tried putting the external call to the get method into the update() method to see if it would pick up the value once the config script had executed and it still constantly spits out 0's at me, so im not convinced this is a problem with the order things are called in.
     
  5. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    That's actually not the case...you should be able to create instances of objects anywhere. You're correct that Awake() is called once, and that it can't use yield. Since yield turns a function into a coroutine, and Awake() can't be a coroutine, though Start() can.

    Something like:

    Code (csharp):
    1. while (!w.isDone || !t.isDone) {
    2.         yield;
    3. }
    instead of "if (w.isDone..." Awake() would call load() once, but load() can be a coroutine. You probably need to make other scripts wait for load() to be done as well.

    --Eric
     
  6. agentcooper

    agentcooper

    Joined:
    Jan 19, 2008
    Posts:
    98
    Thats interesting, the only reason that comment is in there is because I was having an issue where the line:


    Code (csharp):
    1. var example = new WWW(url)
    was causing a problem, I cant remember what the error message was but it mentioned something about Generators cannot return values. I couldn't create an instance of an object and get that same function to return a value.

    Just to be clear, should the "while" be called in the Awake method or in the load() method?
     
  7. agentcooper

    agentcooper

    Joined:
    Jan 19, 2008
    Posts:
    98
    Genius! Having added the while and yeild instructions to load() it works now!

    Eric you will definitely be getting a top spot in my credits when this is published! You have helped on pretty much all of my posts.
     
  8. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    You'd get that message if you tried to make a coroutine return a value. I think it can be a bit confusing sometimes having functions do two different things; it might be nice if there was "function Something()" and "coroutine SomethingElse()" to make it more clear. But there isn't, so I guess it's just something to be aware of. :)

    In load(). You need to use yield so it couldn't be in Awake().

    Edit: Oops, didn't see your last post there. ;) You're welcome.

    --Eric
     
  9. agentcooper

    agentcooper

    Joined:
    Jan 19, 2008
    Posts:
    98
    No problem! ok I do have one last question... is there a way to stop a coroutine executing? I have found the stopCoroutine in the API but it seems like it would not fit in here. I could just set it to a huge number of seconds in the WaitForSeconds() method but I would like to stop it if possible.
     
  10. Eric5h5

    Eric5h5

    Volunteer Moderator Moderator

    Joined:
    Jul 19, 2006
    Posts:
    32,401
    Yes, StopCoroutine is useful, though it seems to be necessary to explicitly start a coroutine with StartCoroutine in order for that to work. (At least that was the case in the past; not sure if 2.0 might have changed it.)

    Another way of stopping a coroutine is to use "return".

    Code (csharp):
    1. if (someCondition) {return;}
    That way the coroutine will exit when someCondition is true. If you used a global variable, you could set someCondition true in another function, which would cause the coroutine to stop.

    --Eric
     
  11. agentcooper

    agentcooper

    Joined:
    Jan 19, 2008
    Posts:
    98
    excellent! All working like a dream now! All I did was to set a static variable (boolean) to false in the config script, which the coroutine sets to true as soon as the WWW calls have been parsed.

    Actually not as soon as, I have thrown a 1 second delay in at the mo to be safe. All the other scripts now have Start() methods that yield until config.allLoaded = true.

    Thanks again for all your help Eric - just the setting of the sky dome texture im stuck on now :D lol