Search Unity

C# Accessing Variable Without Object Refrence

Discussion in 'Scripting' started by sherlockturtle, Mar 5, 2015.

  1. sherlockturtle

    sherlockturtle

    Joined:
    Jan 23, 2012
    Posts:
    592
    Essentially I have had a lot of trouble manually saving all the variables in my game(there are many). I wanted to just make it so it will only have to save one variable(an object). So, I put all the variables in my game into a custom class and then make a new instance of that at the beginning of the game. For example:

    Code (csharp):
    1.  
    2. public class SaveVariables(){//Class with all my variables in it
    3. public int x;
    4. public int y;
    5. public int z;
    6. }
    7.  
    Code (csharp):
    1.  
    2. public SaveVariables theVariables = new SaveVariables();
    3. game functions.....
    4.  
    And that works for saving, but I am having an issue since all my variables are not referencing the class(theVariables). For example: before I could have said "z", but know I have to say "theVariables.z". I am wondering if there is a way to do this so I don't have to write theVariables each time.

    Basically, is there any way to make it so I do not need to write the object reference? So, it will see x and know it is the x variable in theVariables? I don't think there is a way to do this, but I thought id ask. I guess most likely I will have to manually serialize each variable and deserialize it to load/save.


    Thanks!
     
  2. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    One super object that is the one and only instance of its kind and needs to be accessed any time by any class without a reference?

    Sounds like you could use a singleton :D

    Code (CSharp):
    1. public static MyClass thisInstance = this;
    Declare a static reference of your SaveVariables class inside of the SaveVariables class, then all of your public variables in that class can be accessed from anywhere anytime via SaveVariables.thisInstnace.varname
     
  3. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    Short answer: no. It wouldn't make sense, as you need to tell the different X's apart. You might have several objects of the SaveVariables class, and picking one of them to be represented by the variable name would be confusing.

    Long answer:
    So, you could do this:

    Code (csharp):
    1. int x = theVariables.x;
    2. Debug.Log(x); //Prints the value of x
    3.  
    BUT, that will only copy the value of the x variable, and not reference it. So if you change the new x-variable, that won't change the variable of the object:

    Code (csharp):
    1. theVariables.x = 5;
    2. int x = theVariables.x;
    3. x = 13;
    4. Debug.Log(theVariables.x); //prints '5'
    If x was an object itself, though, and you changed that object, the change would happen. This has to do with the difference between value types (numbers, enums, structs), and reference types (classes), and I'd recommend googling up on it.

    Would have written "inb4 someone in the Unity community answers a question with 'try singletons' regardless of topic", but I see that's already too late.
     
  4. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    @Baste Just need to make good use of the singletons :p

    If the need was that you wanted 2 objects at any given time to know each other's x position, then both objects could be referenced by a singleton. "One variable, one object, referenced by all" sounds pretty singleton-worthy to me. You don't have a lot of good uses for singletons in regular programming, but in gaming for a lot of things, it makes sense.
     
  5. Juice-Tin

    Juice-Tin

    Joined:
    Jul 22, 2012
    Posts:
    245
    @Tomnnn I think he's asking a way to avoid the prefix before the variables, so he doesn't need to type out 'theVariables.x' everytime, instead of just typing 'x'

    In some languages for example you can do this:

    Code (csharp):
    1.  
    2. public SaveVariables theVariables = new SaveVariables();
    3. with(theVariable){
    4. x = 5;
    5. y = 7;
    6. z = 10;
    7. }
    8.  
    But not in C# unfortunately, though you can always shorten the variable name!
    Code (csharp):
    1.  
    2. public SaveVariables sv = new SaveVariables();
    3. sv.x = 5;
    4. sv.y = 7;
    5. sv.z = 10;
    6.  
    Though Tomnnns Singleton is still a great way to set up saves anyway.
     
  6. Antistone

    Antistone

    Joined:
    Feb 22, 2014
    Posts:
    2,836
  7. knr_

    knr_

    Joined:
    Nov 17, 2012
    Posts:
    258
    Hi sherlock,

    What we do is we use one class, called GameData, where we (as you might have guessed) have all the game data. We store an incredible amount of data in this class - so much that we can reproduce a player's every move (at least for our current project - for other projects it would not make sense to reproduce their every move).

    For saving the data out somewhere and loading it back when we use a JSON serializer (LitJson). LitJson can take a class, recursively go through it and serialize all the data into a nice, tidy JSON string. In our case that string gets sent to a database somewhere on the Internet and when a player wants to play that game it retrieves the game data in that JSON string stored in the database and then deserializes the data into the GameData class - which again, is made up of both intrinsic (integer, float, string) types as well as our own classes.

    So yes, you can build a single data structure (class) that houses all the information you desire to save out, and work with that, instead of serializing / deserializing each and every member variable.

    Example. Below are some classes that would contain data you would like to get and save (I'm keeping it simple and generic but you can probably get the idea):

    Code (CSharp):
    1. using System;
    2. using System.Collections.Generic;
    3.  
    4. class GameData
    5. {
    6.    public GameData()
    7.    {
    8.       m_GameID = 0;
    9.       m_Players = new List<Player>();
    10.    }
    11.  
    12.    public Int32 m_GameID
    13.    public List<Player> m_Players;
    14. }
    15.  
    16. class Player
    17. {
    18.    public Player()
    19.    {
    20.       m_PlayerID = 0;
    21.    }
    22.  
    23.    Int32 m_PlayerID;
    24. }
    and then somewhere in code, if you add LitJson to your Unity project somewhere:

    Code (CSharp):
    1. // Save Game Data
    2.  
    3. ...
    4. // assumes that there is a variable gameData declared of type GameData somewhere...
    5. String jsonStringGameData = LitJson.JsonMapper.ToJson(gameData);
    6.  
    7. // send the string to a save game file, database, or anywhere you want
    8.  
    9. ...
    Code (CSharp):
    1. // Load Game Data
    2.  
    3. // Convert the json string stored in a file, database or wherever
    4. // into the classes they represent along with their saved values
    5.  
    6. ...
    7.  
    8. GameData gameData = LitJson.JsonMapper.ToObject<GameData>(jsonStringGameData);
    9.  
    10. ...
     
    Last edited: Mar 5, 2015
  8. User340

    User340

    Joined:
    Feb 28, 2007
    Posts:
    3,001
    With Object Initializers, you don't need to write the variable name each time you set a field or property. See:
    Code (csharp):
    1. Color skyColor = new Color
    2. {
    3.    // property list
    4.    r = 0.2f,
    5.    g = 0.5f,
    6.    b = 0.9f
    7. };
     
  9. Tomnnn

    Tomnnn

    Joined:
    May 23, 2013
    Posts:
    4,148
    @Juice-Tin it's usually necessary to read into the asker's needs since a lot of them are new to programming :p I wasn't sure if this was actually about saving data to a disk, saving data between scenes, or just... storing it somewhere. "save" has pretty clear meanings, but the code snippets & attempts indicate more of a need for storage during runtime.

    @rnakrani actually posted a saving feature. Now we've covered all (most?) possible cases for this question.
     
  10. sherlockturtle

    sherlockturtle

    Joined:
    Jan 23, 2012
    Posts:
    592
    Hey all! Thank you for the plethora of responses. I understand how to save my data, I just had the issue of trying to make it easier to save so I only had to manually reference one object instead of every single variable, but then I would have to retype all my variable references to include the object reference.

    Juicy-Tin was correct by the way "@Tomnnn I think he's asking a way to avoid the prefix before the variables, so he doesn't need to type out 'theVariables.x' everytime, instead of just typing 'x'" I am trying to avoid the prefix before the variable so I don't have to write it out each time because I already wrote all my code and I don't want to write the object reference in front of EVERY variable.

    Thank you Tomnnn for all the thoughts, and Singleton is not what I am looking for, but definitely an interesting concept and idea for other things!
     
    Last edited: Mar 5, 2015