查看: 1369|回复: 3
打印 上一主题 下一主题

untiy3d脚本系列知识2-Unity3d Singleton scripts : To be or not to be…

[复制链接]

2508

主题

2

听众

3万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
32806
精华
12

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2012-8-3 17:44: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 !
分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

2508

主题

2

听众

3万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
32806
精华
12

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

沙发
发表于 2012-8-3 17:54:37 |只看该作者
我爱纳金网~www.narkii.com
回复

使用道具 举报

2317

主题

54

听众

2万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
20645
精华
62

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

板凳
发表于 2012-12-30 15:48:35 |只看该作者
学习了,虽然还是有难度,谢谢楼主的用心  
回复

使用道具 举报

2722

主题

42

听众

3万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
38268
精华
111

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

地板
发表于 2012-12-31 01:51:07 |只看该作者
谢谢楼主的帖子分享,学习了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2025-7-24 00:00 , Processed in 0.083197 second(s), 28 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部