Game initialization script

I’m making a blank first scene called Initialize with a blank gameObject with the Initialize script that just runs and goes to a different scene that continues on with the game. How do I set up this script where I can make all of my static classes and static variables? I’m not great at C# and very time I try to set up global variables and global classes it gives me errors and that the script won’t load in the editor. I just want everything declared in the game on startup so I can reference it in any scene in the game. I want to make character classes with variables and arrays and lists etc, how do I do this without making errors? I have problems knowing exactly how to search for what I’m looking for so if there’s a link to a post or thread that already has this that would be great too thanks

How you would write it depends on what you are trying to initialize. Simple example though.

using UnityEngine;

public class InitializeClass : MonoBehaviour
{
    void Awake()
    {
        Debug.Log("Initializing...");
        ImportantStuff.DefaultCharacter = ImportantStuff.Character.Human;
        ImportantStuff.StartingTacos = 17;  //Tacos are yummy, start with a lot of them
        ImportantStuff.LoginBannerText = "Earn experience by eating tacos, don't share with your friends, because they should find their own tacos!";
    }
}


public class ImportantStuff
{
    public enum Character { Elf, Human, Dog, Potato };
   
    public static Character DefaultCharacter;
    public static int StartingTacos;
    public static string LoginBannerText;
}

Please show your code, the exact errors, and what line they are reported at if you continue having difficulty.

1 Like

So i dont need static classes or a static script to make global variables? I want to set up a class called global and put all of my global variables in it so i can just type global.HP for example in any script and it know what im talking about. The same with classes i want to create the character class in the initialize script and set up every attribute each character has for quick calling and referencing anywhere in the game. I tried to create public static classes and tried to create parameters in those classes and it gave me errors

I’ll explain what static actually does, since i believe it may help you. The static modifier makes it so that the member (variable, method, …) belongs to the type itself, not to any specific object instance of the type. Example:

public class Character
{
    public static readonly int MAX_HEALTH = 10;
    public int currentHealth = MAX_HEALTH;
}

A character has a maximum amount of health, which is the same for all characters, and a current amount of health which starts at the maximum and may be dynamically changed (by taking damage for example). The currentHealth attribute belongs to each instance of the Character type. So when we create Characters A and B, both of them have independant values for currentHealth, which makes sense since they can take damage independantly. They both share the same MAX_HEALTH value, which can be accessed from within the object like a normal variable, but can also be accessed from outside any instance by simply calling Character.MAX_HEALTH, since it belongs to the type, not some instance of the type.

Things get a bit tricky when we add static methods. Since the static method belongs to the type and not to any specific instance of the type, you may not access any instance-specific members. For example, you can not access currentHealth from within a static method, since the method belongs to the type itself, which can not have a changing state and thus does not have a value for currentHealth (and it obviously cant randomly chose a value from one of its instances).

Your problems may be rooted in a weird usage of static methods. If that’s the case, then maybe the above explanation can help you figure it out. Otherwise i dont think we can do much more without seeing some code.

So, what I want is classes and variables that can be grabbed in any object, in any scene, and the script knows what I’m talking about. So I want to declare all of my stuff at the very beginning of the game, so 5 scenes later when i say (THIS CHARACTER).HP -= 5; and it stores it into the Character class’s HP variable. I want to create the stats for 5 or 6 characters so that when a character levels up it increases its stats and keeps them stored where I can grab them from anywhere at any time. Maybe I’m not articulating what I want exactly. Will a public class allow me to call it from anywhere? So if I make a character class and make a new instance of that class, so let’s say I make the character class and put the MaxHP, currentHP, magic, attack, defense, etc variables in it. Then I want to actually make a character using that class. So in that first script of the game I make the character class with those variables in it and then do JEFF = new Character, and JEFF.MaxHP = this and JEFF.currentHP = this. How do I do this to save all of that stuff to call and change later?

Here’s some code.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class global
{
    public enum CharID
    {
        Blank = 0,
        VoidChar = 1,
        FireChar = 2,
        EarthChar = 3,
        WindChar = 4,
        WaterChar = 5,
    }

    public Character VoidChar;
    public Character FireChar;
    public Character EarthChar;
    public Character WindChar;
    public Character WaterChar;
}

public class Character
{
    public int id;                                                  // Which character is it
    public bool available;                                          // Is character unlocked
    public string name;                                             // Character name
    public int trueMaxHP;                                           // Character true max HP
    public int maxHP;                                               // Character max HP
    public int HP;                                                  // Character current HP
    public int trueMaxMP;                                           // Character true max MP
    public int maxMP;                                               // Character max MP
    public int MP;                                                  // Character MP
    public float healthCorrupt;                                     // Character health corrupt
    public float magicCorrupt;                                      // Character magic corrupt
    public int attackPower;                                         // Character attack power
    public int defensePower;                                        // Character defense power
    public int magicPower;                                          // Character magic power
    public int jumpHeight;                                          // Character jump height
    public int runSpeed;                                            // Character run speed
    public int weight;                                              // Character weight
    public bool[] unlockedSpells;                                   // Array for unlocked spells
    public int[] spellWheel;                                        // Array for bound spells
}


public class Begin : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        //Set up characters
        global.VoidChar = new Character
        {





        };








        //Go to first room
        SceneManager.LoadScene("EarthTemple");
    }
}

So, I’m trying to create a list of character stats to call and edit later. Whenever I try to assign variables, it gives me an error.

As always, there are multiple ways do to everything. As i understand it, you want the following:
1.) Access public classes, like Character, from everywhere. So you can call/create them wherever you want.
2.) A place to store instances of those classes such that you can access them from wherever you want as well.

As for 1:
Generally speaking public classes can be accessed from anywhere in your project in most cases. Outside of Unity you’d have to import the files you want to use first, but Unity internally does that for you. Or at least it should. I believe the process depends on your project folder structure, so if you cant access public classes your project might be organized in a weird or unexpected way. You should technically be able to import any outside file using the “using” directive, which you already use to, for example, import the UnityEngine by default.

As a note seeing your code: I personally am not a big fan of nested classes. You should rather have a file per class, unless it’s a private class only used internally for some other public class. Otherwise your scripts will get really huge and thus hard to work with, very quickly.

As for 2:
I’d suggest using some sort of static or singleton manager class. Which one you pick depends on what you need.
You could use a public static class, in which you save a static list of your characters (or whatever else you want to access). Then you could simply call Manager.characterList to get that list. However, going with the static manager approach, everything in that class needs to be static, since the class will never be instantiated.
For a bit more flexibility, and being able to work with it the same way you are used to with any other instanciated object, i’d suggest using the singleton pattern. A singleton class is basically a class only allows for the creation and accessing of one single instance. To achieve this the class saves a static reference to an instance of itself. It also has a private constructor, which is only accessable through a public static method, generally called something along the lines of “GetInstance()”. When called, this method checks if an instance exist, creates one if it does not, and returns it otherwise. That way only one instance ever gets created and this instance can be accessed from everywhere calling Manager.GetInstance(). This instance is a normal object instance you can use like you are used to. Example code:

public class GlobalManager{

    // private singleton instance
    private static GlobalManager instance;

    // your data, for example:
    public List<Character> characterList;


    // private singleton constructor
    private GlobalManager(){
        // can be used like any other constructor to instantiate stuff (but only gets called once ever):
        characterList = new List<Character>();
    }

    // public static method to access private instance from anywhere!
    public static GlobalManager GetInstance(){
        if(instance == null){
            instance = new GlobalManager();
        }
        return instance;
    }

}

You can then access the singleton instance from anywhere by calling GlobalManager.GetInstance(), and use it like any normal object. For example, use GlobalManager.GetInstance().characterList.Add(someNewCharacter); to add some new character to your global list of characters, then access it somewhere else (“5 scenes later”) by calling GlobalManager.GetInstance().characterList again.
You can expand on this and make your singleton instance save all the data you want to.
If you have any more questions regarding this topic, feel free to ask!

Other than that, in your example you do something like global.CharID.VoidChar = new Character, which doesnt make a whole lot of sense. You are trying to save a Character type in an enum. What you probably want to do is save the ID in the id attribute of your created Character, like so for example:

Character a = new Character();
a.id = (int) CharID.VoidChar;

If that’s not id, then i assume you want to access each character by their id, and each character can and will only exist once? If that’s the case, then you should probably just add them to the characterList in the right order, so for example the VoidChar Character is the second element (at index 1 since we start counting with 0) in the characterList. That way you can get the instance of the specific charactertype by accessing the characterList using its index, like so: GlobalManager.GetInstance().characterList[(int)CharID.VoidChar].

One last thing: everything in your classes is public. As a rule of thumb things that are not supposed to be accessed from the outside (like “trueMaxHp” i’d assume) should be made private and if they are not supposed to change at all (so it’s basically a never changing constant, also probably true for “trueMaxHp”) you can make them static or const as well.

In case i’m correct in the assumption that you are very new to coding, i’d suggest looking up some general tutorials on classes and object oriented programming, so you get a grasp of how things work.

Hope this helps, wish you a nice day :slight_smile:

1 Like

Thanks Yoreki. What I want to do is have a controllable character object be able to swap to any of the 5 playable characters I have. So I think I want an array of Characters, so that when I switch to one certain character it knows what the current character is so that when an enemy hits the player I can say (CurrentCharacter).HP -= 5 or whatever. How do I set up an array of Characters so that whoever is currently being played it can be drawing from that list of stats of that character?

Yeah, well, i’d do it exactly as i described it above. :slight_smile:
Instantiate and add your characters to the list (or array) of characters in the singleton CharacterManager. When you switch a character, simply get the appropriate character instance from that array, either by using its id as index, or by iterating over the entire list and looking for the right character by some other means. Keep in mind tho, that these character objects only define
Is there anything i should try and explain a bit more in-depth? Or anything else you have problems with?

One more quick note on your code example. I like having lots of comments, however they gotta be meaningful. If you have a class named Character and a variable named healthCorrupt, then what knowledge do i gain by reading the comment “Character health corrupt”?
Just a piece of advice, but sooner or later comments that are not beneficial, will end up being decremental to readability.

Also consider deleting the other thread you opened if possible. Generally speaking, opening multiple threads for the same topic is not a welcome sight on any forum. If everybody did it, there would be countless half-answered threads cluttering the forum and the search function and everybody would have a harder time on the forum, including the ones looking for an answer.
(Also, this thread is definitely not too long. There are some threads that are like 400 pages long in some forums ^^)

I think I just don’t know how to organize it. I want to set everyone’s starting stats in the initialize script, make one object that is manipulated by the array’s values depending on what the run speed is or the weight or height of the character. I’ve made one animation controller that governs what character is what based on their sprites, whenever the currentChar variable is a certain number, maybe I need to create a Party class that has every Character in it, I’m new to C# not to programming in general, I just need to understand the syntax, I want when I push a key or gamepad button it cycles through the current playable characters. I want the entire array to run based on what the currentChar variable is, so I can quickly switch between characters like Marvel Vs Capcom but with an entire party, instead of just 2 or 3. Sorry if I keep asking the same question in different ways. I’ll put some code together and put it up to see if I get what I want, thanks

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class globalVar
{
    public enum CharID
    {
        Blank = 0,
        VoidChar = 1,
        FireChar = 2,
        EarthChar = 3,
        WindChar = 4,
        WaterChar = 5,
    }
}

public class Character
{
    public int id;                                                  // Which character is it
    public bool available;                                          // Is character unlocked
    public string name;                                             // Character name
    public int trueMaxHP;                                           // Character true max HP
    public int maxHP;                                               // Character max HP
    public int HP;                                                  // Character current HP
    public int trueMaxMP;                                           // Character true max MP
    public int maxMP;                                               // Character max MP
    public int MP;                                                  // Character MP
    public float healthCorrupt;                                     // Character health corrupt
    public float magicCorrupt;                                      // Character magic corrupt
    public int attackPower;                                         // Character attack power
    public int defensePower;                                        // Character defense power
    public int magicPower;                                          // Character magic power
    public int jumpHeight;                                          // Character jump height
    public int runSpeed;                                            // Character run speed
    public int weight;                                              // Character weight
    public bool[] unlockedSpells;                                   // Array for unlocked spells
    public int[] spellWheel;                                        // Array for bound spells
}

public class Party
{
    public Character VoidChar;
    public Character FireChar;
    public Character EarthChar;
    public Character WindChar;
    public Character WaterChar;
}

public class Begin : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        //Set up characters

        //CREATE CHARACTER
        //SET ALL OF CHARACTERS VALUES AS INTO ONE CHARACTER
       
        //REPEAT FOR THE REST OF THE CHARACTERS
       
        //STORE ALL OF THE CHARACTERS INTO AN ARRAY

        //BE ABLE TO CALL ANY CHARACTER VARIABLES BASED ON WHAT THE ARRAY INDEX IS

        //Go to first room
        SceneManager.LoadScene("EarthTemple");
    }
}

Ok, so I can set the Characters up I know how to do that, I just want to store all of the characters into an array, and pull out any stat I want, how do I do that? I think I make a new class right? one that can store all of the characters I made into an array correct?

You say you are new to C#, not programming. Are you new to object oriented programming in general? Because imho that’s all pretty much the same. C#, Java, partly C++, and many more, you can copy-paste 90% of the code around.
If you are new to object oriented programming, but not programming itself, then the most obvious route would be to look up some tutorials on object oriented programming, so you get a grasp of what classes and objects and stuff actually are meant to be.
That said, objects are just types that can contain types, to make it easier for the programmer to form logical relations between groups of data. This is obviously a very simplified view, so please go through some in-depth tutorials.
You have a Character, which is a type. So yes, you want an Character[ ] (arrays have fixes length) or List (lists have dynamic length) to store your characters in some class. In my example i used a List, called characterList, in which you could store your characters.
Please read my long comment again, since i pretty much explained all you need to do to save a list of characters, which you can access from anywhere, there. It’s also mostly tailored for your problem and thus pretty much code and examples you can copy paste.
Somewhere you will then instantiate your characters and assign their values, for example like this:

Character void = new Character();
void.id = 1;
void.name = "ThePropagation";
void.trueMaxHp = 10;
/*
* instantiate all the other values here.
* note that some are probably constant values like trueMaxHp
* so you could assign those directly in the class definition instead
*/
void.spellWheel = new int[10];

After you defined all your Characters you’d then assign them to your list of characters by calling for example (listname).Add(void). Now the character with the values we assigned above was inserted as the last / new element in the list. If you want the list to be accessible from each and every script, use the approach i described in my long post and access it by calling Manager.GetInstance().characterList.Add(void) instead. Does the same thing, is just accessible from everywhere.
Now, you either directly insert them in the right order, so “Blank” is the first element you insert, “Void” the second and so on; which results in very fast access since you already know that if you need the void character, it’s the element at the 1st index (which is the id of the void character from your enum). If, for some reason, you dont want to do that, you’d just save them in whatever order you want, and later go through each saved character and look for the one you want, for example like so:

foreach(Character c in Manager.GetInstance().characterList){
    if(c.id == CharID.VoidChar){
        // then c is the void character
    }
}

Again, most of all you need to do is already covered in my longer post, and when you repeat things i explained there i kind of get the feeling you didnt read it. Again, if something was too complicated for you then i’ll gladly explain that part in easier terms.