Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

Script w/ no link between the components is working... why?

Discussion in 'Scripting' started by Adam-Buckner, Feb 11, 2009.

  1. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    As you can tell, I'm having some fun learning how to cobble together something that works! (And it is fun...)

    And I've been ironing out how to cache links between components...

    ... and then I run across an old script that's been chugging away for a while...

    ...

    ... and I stare at it...

    ...

    It shouldn't work.

    How can this possibly work?

    There is no link between the components...

    ... but it does?

    Works fine...

    Why?

    Code (csharp):
    1. GUIData.js
    2.  
    3. @script ExecuteInEditMode()
    4.    
    5. function Update () {
    6.    
    7.     if (ShipController.currentVelocity.magnitude > 1) {
    8.         guiText.text = (Mathf.Round(ShipController.currentVelocity.magnitude)) + "\n" + (Mathf.Round(PlayerStatus.currentFuel)) + "\n" + (Mathf.Round(PlayerStatus.currentHealth)) + "\n\n" + PlayerStatus.currentLives + "\n" + PlayerStatus.currentCargo + "\n\n" + PlayerStatus.currentScore;
    9.    
    10.     else{
    11.         guiText.text = "0" + "\n" + (Mathf.Round(PlayerStatus.currentFuel)) + "\n" + (Mathf.Round(PlayerStatus.currentHealth)) + "\n\n" + PlayerStatus.currentLives + "\n" + PlayerStatus.currentCargo + "\n\n" + PlayerStatus.currentScore;
    12.     }
    13. }
    It's attached to a gameObject with a GUIText Component.

    It's the child of Level Attributes gameObject that contains this and other GUIText Scripts and the LevelStatus script.

    None of the components or child components find or get any components or objects...

    I'm thoroughly mystified.

    How can it know what ShipController or PlayerStatus is?
     
  2. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    I would hazard to guess there's a static declaration involved.
     
  3. Jacob-Williams

    Jacob-Williams

    Joined:
    Jan 30, 2009
    Posts:
    267
    Given the above quote, there are two possible reasons:

    1)The ShipController and PlayerStatus reference the scripts, not the components. (For example, ShipController.currentVelocity looks for a script named "ShipController" and a variable named "currentVelocity.") I would wager that you have those scripts attached to the required components.

    Or...

    2)I am new to Unity and I have no idea what I am talking about.

    Choose wisely...
     
  4. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Quietus: I'll follow your suggestion. If you have any more info on Static Declarations that would help me on my search, that would be great. But I'll be looking up Static Declarations pronto...

    CheapDevotion: Intrigued... Those are other scripts attached to other gameObjects, and variables in those scripts, being accessed. Tho' I'm not sure what you mean by:
    :wink: They are all attached to where they are supposed to be! :D On other gameObjects! :eek: There is nothing, however, attached to current gameObject or child components that would create a defacto link - like all being associated with the same gameObject.

    To be pedantic, there is no link or cache anywhere in the gameObject, nor any static calls in the gameObject that I know of:

    The full information on that gameObject is:

    The script GUI Data Text (in the opening post)is attached to a root level game object called Level Attributes.



    It shares a child level/space with a spawn point gameObject : Transform Script declaring a gizmo.

    Code (csharp):
    1. SpawnPoint.js
    2.  
    3. function OnDrawGizmos() {
    4.     Gizmos.DrawIcon(transform.position, "Spawn1.psd");
    5. }
    There is the GUI Data script:

    Code (csharp):
    1. GUIData.js
    2.  
    3. @script ExecuteInEditMode()
    4.    
    5. function Update () {
    6.    
    7.    if (ShipController.currentVelocity.magnitude > 1) {
    8.       guiText.text = (Mathf.Round(ShipController.currentVelocity.magnitude)) + "\n" + (Mathf.Round(PlayerStatus.currentFuel)) + "\n" + (Mathf.Round(PlayerStatus.currentHealth)) + "\n\n" + PlayerStatus.currentLives + "\n" + PlayerStatus.currentCargo + "\n\n" + PlayerStatus.currentScore;
    9.    
    10.    else{
    11.       guiText.text = "0" + "\n" + (Mathf.Round(PlayerStatus.currentFuel)) + "\n" + (Mathf.Round(PlayerStatus.currentHealth)) + "\n\n" + PlayerStatus.currentLives + "\n" + PlayerStatus.currentCargo + "\n\n" + PlayerStatus.currentScore;
    12.    }
    13. }
    The GUI Category Text:

    Code (csharp):
    1. GUICategory.js
    2.  
    3. @script ExecuteInEditMode()
    4.    
    5. var textVelocity = "Velocity: ";
    6. var textFuel = "Fuel: ";
    7. var textHealth = "Health: ";
    8. var textLives = "\nLives: ";
    9. var textCargo = "Cargo: ";
    10. var textScore = "\nScore: ";
    11.  
    12. function Update () {
    13.    
    14.     guiText.text = textVelocity + "\n" + textFuel + "\n" + textHealth + "\n" + textLives + "\n" + textCargo + "\n" + textScore;
    15.  
    16. }
    And finally the announce text (which is set from another script:

    Code (csharp):
    1. GUIAnounce.js
    2.  
    3. @script ExecuteInEditMode()
    4.    
    5. var textMessage = "";
    6.  
    7. function Update () {
    8.    
    9.     guiText.text = textMessage;
    10.  
    11. }
    I don't see anything in this gameObject that could set up a connection.
     
  5. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Is this because in PlayerStatus ShipController, these variables are static?

    Code (csharp):
    1.  
    2. PlayerStatus.js
    3.  
    4. static var LTOFuel : float;
    5. static var LTOHealth : float;
    6. static var LTOLives : int;
    7. static var LTOCargo : int;
    8. static var LTOScore : int;
    9.  
    Code (csharp):
    1. ShipController.js
    2.  
    3. static var LTOVelocity : Vector3;
    4.  
    From what I gathered, these needed to be static to be shared...
     
  6. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    Sure. When you declare a variable or function as static, it's then available to the entire project without needing to go through all that caching that we had talked about earlier. Sounds great right? However it comes with some very dangerous 'gotchas.'

    So let's take an example.

    Code (csharp):
    1.  
    2. static var myLives = 3;
    3.  
    So I have a script attached to my player, where I define the number of lives he has. I declare it as static, because I'm lazy and I still want all my scripts to have access to the number of lives he has. Given a usual configuration, I attach this script to my player game object in scene 3. With scene 0 being a splash screen and scene 1 being a main menu.

    Gotcha #1:

    The script is now accessible not just in scene 3, but also in scene 0 and scene 1! But wait, I don't attach it to any game object before scene 3! That's right, the values are now per-script and not per-instance of that script.

    That's because things declared as static are implemented at the class level, and are therefore now independent of any game object. There is only one copy of myLives for the entire project. That means if you have 30 copies of a script containing myLives, they are all going to share the same value. Oops!

    Gotcha #2

    A by-product of this fact, is that a static declaration is also persistent. Attach your script to a game object, change the value of myLives. Delete the game object and repeat. The variable myLives will still have your altered value from the previous iteration!

    So if you use a static variable, you can't count on going back into a scene and having the recreation of game objects to reset your variable's values to an initial condition. You need to do it by hand!

    To summarize...

    While static variables can have some benefits, if you're not extremely careful then they can also cause some major WTF moments and debugging nightmares. I use them in a general game settings singleton, or for other project wide code that's independent of any gameObject. Other than that I'm extremely cautious, as they bit me in the arse before I had more experience.
     
  7. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    I was right, do I win a prize? Free game art?
     
  8. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Sure! Free game art! (Does it have to be good?)

    When I got started (not that long ago) I read somewhere that variables needed to be static to be shared (some tutorial? some post?), and as I stumbled along it must have solved some problem or other...

    ... and they've stayed that way.

    I guess the authors were not definitively wrong, just incomplete in their advice.

    These are all single instances, tho' not true singletons (a subject I am still studying like my 5 m.o. son studies his colorful mobiles over his bed...), but as I've yet to start (and am getting into this week) the exercise of loading a second playable game level (test, in this case) that I'm going to need to know singletons and dontdestroyonload and all that crepe paper.

    The scales fall from my eyes?

    Hrm...

    Got a ways to go, I think...
     
  9. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    It can't be any worse than mine!

    I made the same mistake for the same reasons. I can't quite remember where I read it though. Probably just did a search on the forums for 'global variables.' I don't believe Unityscript is really covered much in the official documentation, so you can't blame Unity.

    I discovered the horrors of static declarations much in the same way, when my game expanded beyond one simple scene.

    I wouldn't really say that a player controller is a good candidate for a singleton. You might get it to work with a hammer and a baseball bat, but that doesn't mean it's a good thing.

    1) Is this variable or function really needed project wide?
    2) Is it independent of any game object?

    You can come up with a set of categories like the above to help you decide. A setting such as masterGameVolume might fit. Shipfuel? I wouldn't think so.
     
  10. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    D'oh!

    I can tell by rereading that I was confusing. Like I said, the definition of a singleton vs. a single instance of a single game object is right on let edge of my grok field, but I didn't mean to imply that PlayerStatus would be one.

    I meant that I'd probably need one, and certainly need something that is persistent to track game level data.
     
  11. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    It's also 6am here and I haven't yet had my coffee. So it might not be you!

    Nod. Well now that you're armed with some knowledge you can come up with a solution that works, is actually designed with intent and that you feel comfortable with. That's a much better situation than just declaring all your variables as Static now isn't it!
     
  12. AngryAnt

    AngryAnt

    Keyboard Operator Moderator

    Joined:
    Oct 25, 2005
    Posts:
    3,045
  13. Adam-Buckner

    Adam-Buckner

    Joined:
    Jun 27, 2007
    Posts:
    5,664
    Angry Ant: I'll get to the singleton thing later. (I've read your entry and the AManager entry in the UnifyWiki... I understand the concept, but I'm struggling with the application of it... More on that later...)

    Quietus: If static variables are so powerful and persistent, why not just create one script, that is NOT attached to any game object, that collects all the global variables that you need in a game? Score comes to mind.

    I can clearly see the problem with instantiated scripts and the worry that there might be multiple versions, but - if you don't need to instantiate the script, I'm failing to see the drawback with maintaining one that is never attached and instantiated.

    Immediately, I could see a Global.js that just sits in the scripts folder which has something like (bodging the code now...)

    Code (csharp):
    1. //Global.js
    2.  
    3. static var score : int;
    4. static var rank : int;
    5. static var achievements : //some list of achievements that could be turned on and off
    6. static var secretSpecialsFound : int;


    Now, wikipedia merely sums up static variables as dangerous and unpredictable, but this seems to stem from the same issue - multiple instantiations. I'd assume, static variables could also suffer from access or changes from multiple sources at the same time (two functions fighting over the same variable) - but in the case of a number like score, there should be only one object with one component adding to that score value... or at least only one at a time... unless your being "creative" with your points allocation (points per time points per success... both accessing the same static variable...) But that would be poor design, or at least poor use of the design knowing you were using a static variable.

    What am I missing?
     
  14. Quietus2

    Quietus2

    Joined:
    Mar 28, 2008
    Posts:
    2,058
    Not much, something like that would probably work out fine. Just be aware that when you want to reset your game, you need to have a function somewhere that sets all the values to their default.

    You see, Little, it's not about never ever using Static variables. It's about understanding what they are and what dangers you can come across. Now you are structuring your design based upon a single player game and just using static vars as a global. Thats fine, not really so object oriented but it'll work.

    If you're making a multiplayer game, you can see where you would likely chose a different tact, with DonDestroyOnLoad probably coming into play between levels.

    What you are doing now is a far cry from some people on the forums who have in the past advised people, "Just make everything a static, then you can access your scripts from everywhere!"
     
unityunity