开发过稍微复杂一点的游戏的人大概都遇过这个状况:
●●●
写了一个负责掌控全局的脚本(许多人习惯命名为GameManager),它知道玩家现在几等、
目前是处于第几关、游戏是进行中or暂停中,所有需要使用它资讯的物件都必须在程式码
中宣告并引用之,并且还要开发者自己去拉reference(如图),如果线没牵好,游戏甚至
还有可能强制终止。
●●●
https://i.imgur.com/gqwJv0u.jpg
当你在其他脚本里撰写了public GameManager GM;,就会看到上图的画面。这个步骤本身
是正确且可行的,然而,在降低耦合性的程式设计原则下,这并不是工程师所崇尚的作法
。
既然自始至终,所有物件提到的GameManager都是指涉同一个对象,无一例外,那有没有
什么方法可以避免这一再拉reference的步骤呢?
这时,我们可以借助C#的一个特性,单例(Singleton)。
单例,顾名思义,就是在整个系统架构里面,这个脚本只会有唯一一个代表人,可以免去
手动指定的流程。
https://i.imgur.com/vPmOtZK.jpg
如图中第7行,我们创造了一个公开(public)但静态(static)的GameManager,并且命名为
Instance(这也是习惯上的命名,要取名做TheChosenOne也可以XD)。
再来看到第12行的Awake()函式,我们必须把Instance指向this,也就是GameManager它自
己。
经过这两个步骤,就完成单例的宣告了。
注:之所以将单例的指定放在Awake()里面,是为了让这一层关系早在其他脚本呼叫Insta
nce前就搭建起来,避免其他脚本在Start()呼叫了Instance,却获得Instance是null的状
况。
https://i.imgur.com/Nnzp0NR.jpg
我们再开另外一个脚本来检查结果,当我按下键盘的S键时,就会在Console中显示当前的
关卡,而关卡资讯是来自GameManager.Instance.curStage。
https://i.imgur.com/e0ad8eL.jpg
如此一来就不再需要第7行的宣告,也不用亲手帮每一个物件挂上GM的reference,可说是
一个便捷又具有设计美感(?)的做法,在越大型的专案里功效就越显著!