读书人

【Unity技艺】使用单例模式Singleton

发布时间: 2013-10-08 16:38:32 作者: rapoo

【Unity技巧】使用单例模式Singleton

这几天想把在实习里碰到的一些好的技巧写在这里,也算是对实习的一个总结。好啦,今天要讲的是在Unity里应用一种非常有名的设计模式——单例模式。


开场白
单例模式的简单介绍请看前面的链接,当然网上还有很多更详细的介绍,有兴趣的童靴可以了解一下。其实设计模式对于一个程序员来说还是非常有用的,这点随着学习的深入感受越来越深。
好啦,现在说一下Unity里的单例模式。什么时候需要使用单例模式呢?正如它的名字一样,你认为一些东西在整个游戏中只有一个而你又想可以方便地随时访问它,这时你就可以考虑单例模式了。例如,你的游戏可能需要一个管理音乐播放的脚本,或者一个管理场景切换的脚本,或者一个管理玩家信息的通用脚本,又或者是管理游戏中各种常用UI的脚本。事实上,这些都是非常常用而且必要的。

实现
庆幸的是,单例模式的代码非常简单。下面是Singleton.cs的内容:


为了证明之前所说的不要在OnDestroy函数里访问单例模式,我们把SingletonSample.cs脚本里注释掉得OnDestroy函数解开注释,然后再次运行。结果如下:【Unity技艺】使用单例模式Singleton

我们注意到,除了Log页面里出现了错误信息外,右侧的场景面板里也多了一个Singleton对象(这是我已经停止运行了)。从Log信息里,我们可以发现,在第一次销毁掉单例模式后,单例模式又再次被创建,但却没有被销毁,由此便残留在了面板里。
正确的做法是,在OnDestroy函数里加一层安全性判断,如下:
void OnDestroy() {if (Singleton.IsCreatedInstance("LitJsonSample")) {LitJsonSample litjson = Singleton.getInstance("LitJsonSample") as LitJsonSample;litjson.DisplayFamilyList();}}


这样,就可以得到正确结果了。
结束语
最后,还有几句话要嗦一下,虽然和单例模式的关系不大,嘿嘿。我们需要注意一下Start函数和Awake函数的执行顺序。在这个例子里,我在LitJsonSample.cs的Awake函数里调用了ReloadFamilyData来初始化数据,细心的童鞋可以发现,在上一篇博文里,初始化数据是在Start函数里完成的。之所以要把它挪到Awake函数里,是为了在我们访问单例时,可以保证数据一定已经被初始化了,因此把初始化函数放到Awake函数里,访问单例的代码放在Start函数里。同样的原因,在Singleton.cs的脚本里DontDestroyOnLoad (gameObject);需要放在Awake函数,而不是Start函数里。关于Awake函数和Start函数的执行顺序,可以详见脚本说明。简单来说,Awake函数在这个脚本在场景中加载时就会调用,至于所有脚本的Awake函数的调用顺序是未知的。然后,在所有的Awake函数调用完毕后,才开始调用Start函数。需要注意的是,Start函数也不是一定立即执行的,它是在该脚本第一次调用Update函数之前调用的,也就是说,如果这个脚本一开始的状态是disable的,那么直到它变成enable状态,在Update函数第一次执行前,才会执行Start函数。两个函数的执行顺序是时间有时正是某些Bug的产生原因!而且这些Bug往往很难发现。哈,我这次实习的面试时,面试的姐姐就问过我这个问题,希望大家也可以搞清楚,如果我这里有说的不对的,请指正。
好啦,这次就到这里,谢谢阅读!

读书人网 >其他相关

热点推荐