【聚光灯-苞米烧烤】开发者日志06 | 苞米单例
本篇由主程老师Ocean撰写,主要探讨单例设计模式——懒人的Lazy单例类,希望对各位游戏开发者和爱好者也有所启发。


单例设计模式似乎是一种……偷懒的解决方式。这玩意儿核心逻辑是,一个类只有一个实例,所有访问这个类的操作本质都在访问这一个成员。个人感觉有一些全局变量的意思了。
那这玩意儿……比全局变量好么?我是绝对它可能在一些别的软件开发中未必提倡,但是游戏开发情景下还真的挺好用的。
比如说,我需要全局追踪玩家的数据,或者是玩家的进度,或者是用来访问常驻资源等等。从某种程度上说,单例设计模式有点“利用面向对象开发模式但是面向过程”。
那,废话不多说,懒人的单例类是要说啥呢。主要是微软.NET里的Lazy<T>。这玩意儿提供了线程安全,简单实用的单例解决思路。具体的原理我也没深挖,反正好用。

(看到那39个引用,说明我有多懒了)
如果我需要某个类是单例类,直接继承,完事了。比如这样:

然后音频相关的全都用这个就好了
但是这样做有一个问题,是单例的脚本没法作为MonoBehavior挂到物体上,咋整。其实上面的截图已经提示了我的解决方案,有点蠢,但是好用。我先创建一个单例B,我再创建一个Mono叫做A,在B里创建一个A的引用,然后在A的初始化(根据需求选择Awake()/OnEnable()/Start())里面调用B,将A的引用赋值一下,然后该干啥干啥就好了。

蠢但好用的解决方案
这么做还带来了一个更有趣的效果,如果我想,我可以让这个引用在不同场景中引用不同的是实例。有啥大用么,未必,但是对测试调试来说绝对是方便了不少。比如说场景切换器,就不需要一直从第一个场景带到后面了。
不过啊,如果我们研究一下单例模式,会发现其实有点不太符合面向对象原则……但是吧,它还是好用的。


苞米即将出炉!敬请期待——!