Search Unity

How to have changeable variables that work between multiple scripts and multiple scenes.

Discussion in 'Scripting' started by The_Fantaz, Apr 8, 2021.

  1. The_Fantaz

    The_Fantaz

    Joined:
    Aug 8, 2020
    Posts:
    16
    I'm trying to make a game that has a currency. I want other scipts to be able to modify/edit the amount, and the variable to be useable on multiple scenes.

    I would use public variables, but I don't know if they work on other scenes, nor do I know if you can change them.
     
  2. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
  3. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
  4. The_Fantaz

    The_Fantaz

    Joined:
    Aug 8, 2020
    Posts:
    16
    To make my variable last multiple scenes, I think that DontDestroyOnLoad() might work.
    However, I still don't know how to (for static fields)
    Acess Them
    Change them from another script...
     
  5. seejayjames

    seejayjames

    Joined:
    Jan 28, 2013
    Posts:
    691
    They can be accessed directly, with no need to get access to the script, because they "live" outside gameObjects. Very handy. And they persist through the entire game. They can be in any script, including ones attached to gameObjects, which is a little unintuitive (at least it was for me). You can also make static classes.

    In any script, say this one's called currencyScript:

    public static int currencyAmount = 5;

    In any other script:

    currencyScript.currencyAmount = 10;
    print(currencyScript.currencyAmount);
     
  6. The_Fantaz

    The_Fantaz

    Joined:
    Aug 8, 2020
    Posts:
    16
    So for the script, do I just make it and NOT put it on an empty gameObject?
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,735
    For static stuff, YES. This may be all you need.

    For DontDestroyOnLoad / Singleton type stuff, the script will get on a GameObject, but not through your direct action.

    Here's the pattern I use for Game Manager-y stuff. There are also plenty of GameManager type tutorials, each one done a slightly-different way:

    Some super-simple Singleton examples to take and modify:

    Simple Unity3D Singleton (no predefined data):

    https://pastebin.com/SuvBWCpJ

    Unity3D Singleton with Prefab used for predefined data:

    https://pastebin.com/cv1vtS6G

    These are pure-code solutions, do not put anything into any scene, just access it via .Instance!

    If it is a GameManager, when the game is over, make a function in that singleton that Destroys itself so the next time you access it you get a fresh one, something like:

    Code (csharp):
    1. public void DestroyThyself()
    2. {
    3.    Destroy(gameObject);
    4.    Instance = null;    // because destroy doesn't happen until end of frame
    5. }
     
  8. The_Fantaz

    The_Fantaz

    Joined:
    Aug 8, 2020
    Posts:
    16
    If I make the script with the static currency variable, would it just be accessable (and changeable) in any script, so I don't need DontDestroyOnLoad() ? Also, I want to use the Start() function to get the money variable from a file (so it doesn't change).

    If the script isn't attached to anything, can it still do Start() , or is the another way?
     
  9. Hosnkobf

    Hosnkobf

    Joined:
    Aug 23, 2016
    Posts:
    1,096
    If you mark it public: yes. However, I would not go for public variables. If you need to set them, do it through a property.

    Start() is only called on classes deriving from MonoBehaviours (and only if they are present in the scene or instantiated during runtime). You can however have a static constructor on a class which is called automatically the first time you access anything of that class.

    Here is some example code...
    Code (CSharp):
    1. public enum Currency { UsDollars, Euros, Yen, }
    2.  
    3. public class MyClass
    4. {
    5.     private static Currency currency = Currency.UsDollars;
    6.     public static Currency Currency { get => currency; set => currency = value; }
    7.  
    8.     private static float money;
    9.     public static float Money => money; // <- lazy property with getter but no setter
    10.  
    11.     static MyClass() // <- static constructor. called as soon as anything of the class is accessed
    12.     {
    13.         string fileContent = System.IO.File.ReadAllText("systemPath/To/File.txt");
    14.         float.TryParse(fileContent, out money); // <- assuming there is just a number in the file
    15.     }
    16. }
    Note: the code above is not tested. Also, you would usually do some error handling to check if the file exists and if the content could be parsed to float.