Hi, I’m looking for some help in setting up a Finite State Machine using the Switch and Case statements for a Game Manager to switch between Scenes.
I’m NOT looking to make a FSM for a character (There are a lot of good links out there for this), but I’m looking to build the Game Manager and how I would switch from scene to scene and use the new scene’s update function without having to revert back to the Game Master class’s update function.
This is what I have working so far:
In Game Master Class I have a enum list with all the difference scenes/levels (eg. Splash, MainMenu, Level01, Leve02…)
I set the enum case to SPLASH (for Splash Page) in the GameManager’s Start Method.
Within Case:SPLASH implement the SPLASH class through an interface called ILevelBase.
In the SPLASH class I call applicationLoadLevel and load the SPLASH scene file.
This is where I am stuck. I want the game loop to reside within the SPLASH class update function, and not jump back to the GameManager class after constructing the SPLASH scene. How do I make the game loop reside in the SPLASH Scene/Class?
Thanks for your help.
A.
Here is my code for my GameManager Class:
using UnityEngine;
using Assets.Scripts.Levels;
using Assets.Scripts.Interfaces;
using System.Collections;
public class GameManager : MonoBehaviour
{
private static GameManager gameManagerInstanceReference;
public ILevelBase activeLevel;
// All the Levels in the game.
public enum LEVEL
{
NULLLEVEL,
SPLASH,
MAINMENU,
LEVEL01,
LEVEL02,
HIGHSCORE,
CREDITS
};
public LEVEL level; // Use this to check the current level and set the current level.
void Awake ()
{
// Check to see if the current Game Manager object exists. If it does then destroy.
if (gameManagerInstanceReference == null)
{
gameManagerInstanceReference = this;
DontDestroyOnLoad (gameObject);
}
else
{
DestroyImmediate(gameObject);
}
}
// Use this for initialization
void Start ()
{
//We are in the START level. We now load the SPLASH Level for Logo and animation, and a countdown.
LevelChange(LEVEL.SPLASH);
}
void Update()
{
// Runs the Level's Update Method - THIS IS WHERE MY ISSUE RESIDES. I DO NOT WANT TO USE THE UPDATE METHOD IN THE GAMEMANAGER FUNCTION TO LINK TO THE ACTIVE LEVEL UPDATE FUNCTION.
activeLevel.LevelUpdate();
}
void LevelChange(LEVEL newLevel)
{
level = newLevel;
// LEVELS FSM
switch (level)
{
case LEVEL.SPLASH:
// load the Splash Level
activeLevel = new Splash(this);
break;
case LEVEL.MAINMENU:
// The currentLevel variable will be switched to MainMenu from the Splash Level Script.
break;
case LEVEL.LEVEL01:
// Load leevl 01 - After the Player Selects "Start" from the main Menu, the currentLevel variable will be assigned Level01
break;
case LEVEL.LEVEL02:
// Load leevl 02 - After the Player Selects "Start" from winning Level 01
break;
case LEVEL.HIGHSCORE:
// Play the High Score. Set the currentLevel variable to Credits
break;
case LEVEL.CREDITS:
// Roll Credits and then set the currentLevel variable to Main Menu.
break;
}
}
public void LevelIsRunning()
{
}
}
What do you mean by the game loop? Unity has the applications game loop defined elsewhere so it is technically not in any specific script. Therefore if the Splash script extends the MonoBehaviour you can simply declare the Update function and move whatever code you want to be looped into that function.
Thanks for the reply Magnite7. I am currently calling the Splash script through an interface.
This is the line of code in the Splash Script
public class Splash : ILevelBase
If I inherit from Mono Behaviour, how would I be able to call the construct of the Splash script through the Game Manager script without an interface? Can I inherit from Monobehaviour and ILevelBase at the same time?
public class Splash : MonoBehaviour
I’m reluctant to respond to this thread because I detect quite a bit of confusion and I don’t have a lot of time now.
Anyways, to answer this:
The answer is: sort of… This is because you don’t “inherit” from interfaces. You “implement” them.
C# doesn’t allow multiple inheritance, but it does allow multiple interface implementation:
class Splash : MonoBehaviour, ILevelBase
However, if you are going to inherit from MonoBehaviour, I think that is to allow this script to exist within a GameObject in the scene.
This is the crux of the issue I think. Instead of creating a Splash object and referring to it through the ILevelBase interface, you would simply create a new prefab with a reference to the Splash script. Creating this GameObject would also instantiate the Splash script since it is an attached MonoBehaviour. At this point, since it is an instantiated MonoBehaviour, the Splash script would start receiving call to the “magical” methods Update(), FixedUpdate(), etc… and you would no longer need to "USE THE UPDATE METHOD IN THE GAMEMANAGER FUNCTION TO LINK TO THE ACTIVE LEVEL UPDATE FUNCTION". At this point you (probably) also don’t need to implement ILevelBase anymore, so the above is a moot point.
The trick, now, would be how to remove the Splash prefab when LevelChange is called on the GameManager…
Hi eiSenpony, this makes a lot of sense! Thanks a lot for your answer!
However it seems like there may be another cleaner way to get to what I want to do other than filling my scene with prefabs for each level I want to eventually load.
Essentially this is what I would want to achieve:
GameManager class to call the Splash class or which ever Level of the game.
The Splash class (or which ever level of the game class) will essentially load the Splash Scene (or Level with its predefined level settings).
Is there a clean way to do this? Perhaps using ScriptableObjects as unity suggests?
Unity throws the following error when when I try the following code when I have the Splash class inheriting from MonoBehaviour
currentLevel = new splash();
Error:
You are trying to create a MonoBehaviour using the ‘new’ keyword. This is not allowed. MonoBehaviours can only be added using AddComponent(). Alternatively, your script can inherit from ScriptableObject or no base class at all
UnityEngine.MonoBehaviour:.ctor()
dope:.ctor()
That’s one possibility - ScriptableObjects can be created using the new keyword and instances also have their Update method called automatically by Unity.
Another possibility, though since it does not inherit from the Unity base class, it will not have its Update method called automatically. You will need to continue calling the update method from your GameManager.
Despite that they might work, I think both of these options are wrong approaches. Unity has a built-in feature for supporting level changes called Scenes. Personally, I think you will be better served looking into switching between scenes in order to do level management.
Thanks for the reply eisenpony. I have for now reverted back to using the GameManager update since I have bigger fish to fry :s
In common practice does one usually have a separate script file for each level? And does this respective Level File save all the Leve’s specific data (time of day, character spawn positions, different camera angles…) and then it loads the new unity scene?
OR
Does the GameManager load the Scene file for the level, which in turn loads a Level File which populates the scene with prefabs?
Currently I have the Game Manager calling the Level File, which in turn loads up the new Scene file. I’m trying to foresee any pitfalls I may run into.
I’d prefer if someone else weighed in on this because I’m just learning the Unity framework myself. Anyways, my understanding is that a scene stores information about the prefabs, objects, cameras, scripts, etc… that are placed into it during edit mode. Loading a new scene should populate all of that automatically. I don’t now if there is anyway to load a new scene without destroying everything in the old one.