Hello, I’ve been messing around with Unity for a couple days, I have “some” experience with UE, but lets say I’m a novice game programmer.
At the moment I’m trying to set up my GameController (I mean a “class”, “script”, “gameObject” where I can set/save level variables or manage the level win/lose).
For what I’ve found in documentations/tutorials, the most used option is creating an emtpy GameObject with a GameController spcrit, where I create “Win()-like” functions.
To me this seems extremely unpractical cause I need to have a: [SerializeField] private GameController _gameController; in every one of my level scripts, to acces it’s (GameController) variables. I guess this could be done, but it seems such a bad practice.
Create any controllers/managers/scripts that you want to access in multiple scenes, in a bootup scene - thats the first scene that loads.
Call DontDestroyOnLoad on that object / script, and it will persist between scene loads. Meaning you can access gamecontroller anywhere
You still need to get a reference to it in any script thats want acces to it though, but its best to do that via a FindObjectOfType in Awake, rather than using SerializeField and manually dragging in (which wouldnt be possible using this method anyway).
I wouldn’t call that “GameController” because that implies something that is controlling your game, ie via user input or a defined linear flow of scenes. Also, input devices for games are often referred to as game controllers, which was my first thought: this being your input handling class.
I’d rather call it the “GameState”. You may want to append “Manager” because that’s a customary thing in Unity, even though it adds nothing to the meaning of such a class. In particular if it doesn’t actually “manage” anything, just load/save variables.
Anyhow, for global state like this, the Singleton pattern can be useful. Alternatively, it could be a static class with only static methods and for saving the state the PlayerPrefs class would suffice for a start.
public static class GameState
{
public static int WinCount
{
get{return PlayerPrefs.GetInt(nameof(WinCount));}
set{PlayerPrefs.SetInt(nameof(WinCount), value);}
}
}
As CodeSmile mentioned, use the singleton pattern for major objects like those and if necessary to persist between levels make them DontDestroyOnLoad. “onLoad” in this case means a scene load as that normally clears all objects of the previous scene unless you load it “additive”.
However since you explicitly ask for best practices:
Especially the first point “Single Responsibility”, that means do not have one class that manages everything! Persisting data, loading next level and tracking score can be split nicely into three classes.
I like defining my own events/delegates and subscribe to them from my other scripts where I actually respond to the input. The input class stays really clean, just processes and raises events if something is subscribing, doesn’t know anything about what is subscribing, doesn’t care.
And I often just make the events static since it is available to anyone who wants to subscribe.
So I have a CustomInput.OnHorizontalAxisChanged, and whether you’re using Input.Axis(“horizontal”), a touchscreen touch, a mouse, a keyboard, an accelerometer, or joystick, I can clean up the x axis and feed it to the same event and no other code has to change downstream.