- 最后登录
- 2017-5-15
- 注册时间
- 2012-3-1
- 阅读权限
- 90
- 积分
- 32973
  
- 纳金币
- 32806
- 精华
- 12
|
Yesterday I found myself to contemplate my Singleton GameObject which is becoming a Nightmare. I had to make a new scene in my game (passed from a zoo scene to multiple scenes) and just found out that i would probably be better off dropping a single Singleton onto a GameObject rather than multiple ones and Re-Edit them all. One Thing I had as a problem was that some of them took reference to the main camera (I have multiple camera settings for various reasons of game play). So I had 3-4 managers that I had to manually select the main camera as reference and it was a bit akward. So I went on to remodel my Singleton Architecture so that most of them where not Singleton anymore but sub-objects of my main game manager.
Main object for synchronization
So I have a main game singleton which is used as a state machine to update the various aspects of the game play. Instead of having a myriads of independent Singleton that are anyways under automatic synchronization, this permits for example to pause the game and not have to check in each of them the current game state (no redundant code).
I Got these states :
enum GameState
{
NOT_SET= 0,
ADVENTURE_MODE= 1,
BATTLE_MODE= 2,
MAIN_MENU_MODE= 3,
CREDIT_MODE= 4,
INITIAL_CINEMATIC= 5
}
with 2 variables :
private var lastState:GameState = GameState.INITIAL_CINEMATIC;
private var state:GameState = GameState.INITIAL_CINEMATIC;
Theses two variable permits me to do state transitioning when there is a state change :
function ChangeState(newState:GameState)
{
lastState = state;
state = newState;
OnStateExit();
OnEnterState();
}
function OnStateExit()
{
Debug.Log("State exit function for state " + StateToString(lastState));
switch(lastState)
{
case GameState.ADVENTURE_MODE:
//Here i do cleaning for this state, that would probably be in my submanager
// such as AdventureManager.CleanUp();
break;
}
}
//This function set transition to enter a new state
function OnEnterState()
{
Debug.Log("State enter function for state " + StateToString(state));
switch(state)
{
case GameState.ADVENTURE_MODE:
//Here you initialize the manager for the mode you are in
// such as AdventureManager.Initialize(...)
break;
}
}
//In this function of the main manager you update other sub managers.
//Since it's the only MonoBehaviour object attached to a GameObject, it is
//the only one who will get the Update, Start, Awake functions.
function Update()
{
switch(state)
{
case GameState.NOT_SET:
break;
case GameState.ADVENTURE_MODE:
if(!DialogMode)
{
AdventureManager.ProcessPlayerInteractions();
}
break;
}
}
Declaring other managers and get access to it
My singleton is usually accessed via its internal static variable such as : GameManager.instance. When you declare another Manager that needs to be updated by you main state manager, you simply declare it public or private (depending on if you want it to be visible as a sub entry in the inspector). Be sure to initialize the variable in Awake. This as the drawback that you cannot change the values in the inspector and keep them when the game start. This is simply because the object exist temporarily in the editor only. Be sure to initialize properly your default values after adjusting them in real time while the game plays in the editor. The good thing even if the values do not persist, you can play with them in the inspector if your sub manager is declared public, and i suggest you do until you are satisfied with the values. Here is an example of my Awake function in my main game manager.
function Awake () {
DontDestroyOnLoad (this);
// This is where the magic happens.
// FindObjectOfType(...) returns the first GameController object in the scene.
instance = FindObjectOfType(GameManager);
if (instance == null)
{
Debug.Log ("Could not locate a LumeManager singleton object. You have to have exactly one LumeManager in the scene.");
}
else
{
if(WorldCamera == null)
Debug.LogError("World camera must be set in LumeManager");
ChangeState(GameState.ADVENTURE_MODE);
AdventureManager = new AdventureModeManager(WorldCamera.GetComponent(Camera));
}
}
Probably all of this is a matter of taste, but as your project grows and you need to set everything up in a new scene each time to test it in a unitary fashion, you will find that adding a single object for your game designer is always easier ! |
|