纳金网

标题: untiy3d脚本系列知识2-Unity3d Singleton scripts : To be or not to be… [打印本页]

作者: 她。    时间: 2012-8-3 17:44
标题: untiy3d脚本系列知识2-Unity3d Singleton scripts : To be or not to be…
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 !
作者: 她。    时间: 2012-8-3 17:54
我爱纳金网~www.narkii.com
作者: 王者再临    时间: 2012-12-30 15:48
学习了,虽然还是有难度,谢谢楼主的用心  
作者: 狂风大尉    时间: 2012-12-31 01:51
谢谢楼主的帖子分享,学习了





欢迎光临 纳金网 (http://go.narkii.com/club/) Powered by Discuz! X2.5