【Unity3D基础教程】给初学者看的Unity教程(七):在Unity中构建健壮的单例模式(Singleton)
作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明。如果你喜欢这篇文章,请点推荐。谢谢!

该博客中的代码均出自我的开源项目 : 迷你微信
为什么需要单例模式
游戏中需要单例有以下几个原因:
- 我们需要在游戏开始前和结束前做一些操作,比如网络的链接和断开,资源的加载和卸载,我们一般会把这部分逻辑放在单例里。
- 单例可以控制初始化和销毁顺序,而静态变量和场景中的GameObject都无法控制自己的创建和销毁顺序,这样就会造成很多潜在的问题。
- Unity3D的GameObject需要动态创建。而不是固定在场景里,我们需要使用单例来创建GameObject。
- Unity3D的场景中的各个GameObject需要从单例中存取数据。
单例的设计原则
在设计单例的时候,我并不建议采取延迟初始化的方案,正如云风所说:
对于单件的处理,采用静态对象和惰性初始化的方案,简直就是 C++ 程序员的陋习。Double Checked Locking is broken,相信很多人都读过了。过于依赖语法糖,通常就会造成这种结果。其实让程序有明显的初始化和退出阶段,是很容易被规划出来的。把单件(singleton) 的处理放在正确的时机,以正确的次序来处理并非难事。
我们应该在程序某处明确定义单例是否被初始化,在初始化执行完毕后再执行正常的游戏逻辑
- 尽量避免多线程创建单例带来的复杂性
- 在某处定义了一定的初始化顺序后,可以在游戏结束的时候按照相反的顺序销毁这些单例
设计单例的基类
在Unity中,我们需要一个基类来为所有单例的操作提供统一的接口,同时,我们还要让所有单例继承MonoBehaviour,只有这样才能让单例自由使用协程这一特性。
基类设计如下,代码链接
using System;
using UnityEngine;
namespace MiniWeChat
{
[RequireComponent(typeof(GameRoot))]
public class Singleton<T> : MonoBehaviour where T : Singleton<T>
{
private static T _instance;
public static T GetInstance()
{
return _instance;
}
public void SetInstance(T t)
{
if (_instance == null)
{
_instance = t;
}
}
public virtual void Init()
{
return;
}
public virtual void Release()
{
return;
}
}
}
设计单例的管理类
除了设计基类之外, 还需要设计一个让所有基类初始化和销毁的类,我们把这个类叫做GameRoot,并且把它绑定在一个名为GameRoot的GameObject上,并且把这个GameObject放在游戏进入的Main场景中。
GameRoot类设计如下,代码链接
namespace MiniWeChat
{
public class GameRoot : MonoBehaviour
{
private static GameObject _rootObj;
private static List<Action> _singletonReleaseList = new List<Action>();
public void Awake()
{
_rootObj = gameObject;
GameObject.DontDestroyOnLoad(_rootObj);
StartCoroutine(InitSingletons());
}
/// <summary>
/// 在这里进行所有单例的销毁
/// </summary>
public void OnApplicationQuit()
{
for (int i = _singletonReleaseList.Count - 1; i >= 0; i--)
{
_singletonReleaseList[i]();
}
}
/// <summary>
/// 在这里进行所有单例的初始化
/// </summary>
/// <returns></returns>
private IEnumerator InitSingletons()
{
yield return null;
// Init Singletons
}
private static void AddSingleton<T>() where T : Singleton<T>
{
if (_rootObj.GetComponent<T>() == null)
{
T t = _rootObj.AddComponent<T>();
t.SetInstance(t);
t.Init();
_singletonReleaseList.Add(delegate()
{
t.Release();
});
}
}
public static T GetSingleton<T>() where T : Singleton<T>
{
T t = _rootObj.GetComponent<T>();
if (t == null)
{
AddSingleton<T>();
}
return t;
}
}
}
如何拓展新的单例
有了以上两个类之后,当我们需要新创建一个类的时候,就可以继承Singleton<T>来创建新的单例,重写Init和Release方法,同时在GameRoot的InitSingleton方法的适当顺序执行AddSingleton<T>方法即可。具体的使用可以参考该类代码链接
【Unity3D基础教程】给初学者看的Unity教程(七):在Unity中构建健壮的单例模式(Singleton)的更多相关文章
- 【Unity3D基础教程】给初学者看的Unity教程(四):通过制作Flappy Bird了解Native 2D中的RigidBody2D和Collider2D
作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明.如果你喜欢这篇文章,请点[推荐].谢谢! 引子 在第一篇文章[Unity3D基础教程] ...
- 【Unity3D基础教程】给初学者看的Unity教程(一):GameObject,Compoent,Time,Input,Physics
作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明.如果你喜欢这篇文章,请点推荐.谢谢! Unity3D重要模块的类图 最近刚刚完成了一 ...
- Unity3D基础知识梳理
这段时间在做Unity的项目,这差不多是我的第一次实战啊~然后公司来了实习的童鞋要学Unity,但是我一向不靠谱啊,所以只能帮他们稍微梳理下基础的东西了啊,唉~学长只能帮你们到这里了~顺便就把自己这两 ...
- Unity教程之再谈Unity中的优化技术
这是从 Unity教程之再谈Unity中的优化技术 这篇文章里提取出来的一部分,这篇文章让我学到了挺多可能我应该知道却还没知道的知识,写的挺好的 优化几何体 这一步主要是为了针对性能瓶颈中的”顶点 ...
- i3D的一篇Unity教程中的笔记
原地址:http://blog.sina.com.cn/s/blog_72b936d80100wwej.html 以下是i3D的一篇Unity教程中的笔记. i3D的这篇教程是[i3D.Next-Ge ...
- Nullsoft教程 NSIS初学者图文教程一
Nullsoft教程 NSIS初学者图文教程一 来源:互联网 作者:佚名 时间:03-29 00:34:33 [大 中 小] Nullsoft Installation System(nsis) 是一 ...
- ios游戏开发 Sprite Kit教程:初学者 1
注:本文译自Sprite Kit Tutorial for Beginners 目录 Sprite Kit的优点和缺点 Sprite Kit vs Cocos2D-iPhone vs Cocos2D- ...
- Sprite Kit教程:初学者
作者:Ray Wenderlich 原文出处:点击打开链接 http://www.raywenderlich.com/42699/spritekit-tutorial-for-beginners 转自 ...
- 专门针对初学者的Node.js教程
转载原文:http://www.csdn.net/article/2013-08-28/2816731-absolute-beginners-guide-to-nodejs Node.js的教程并不缺 ...
随机推荐
- 03-树2 Tree Traversals Again
这题是第二次做了,两次都不是独立完成,不过我发现我第一次参考的程序,也是参考老师(陈越)的范例做出来的.我对老师给的做了小幅修改,因为我不想有全局变量的的存在,所以我多传了三个参数进去.正序遍历每次都 ...
- 使用struts2的<s>标签出错
15:org.apache.struts2.views.jsp.ActionTag 16:JSP 17:18:19:executeResult Server: Resin/3.1.4a Content ...
- Http请求与响应格式
原文:http://www.cnblogs.com/z941030/p/4699779.html Http协议对浏览器发出的Request格式以及对Web服务器发出的Response格式有具体的规定. ...
- node 学习笔记
以下笔记默认安装完成node 及npm 1.安装express 新版本的express-generator已经独立出来,全局安装这个包就ok. npm install express-generato ...
- JQuery源码解析(九)
jQuery回调对象 jQuery.Callbacks一般开发者接触的很少,虽然jQuery向开发者提供了外部接口调用,但是$.Callbacks()模块的开发目的是为了给内部$.ajax() 和 $ ...
- Net作业调度-----Quartz.Net
一:业务需求: 项目需要在不同时刻,执行一个或很多个不同的作业. Windows执行计划这时并不能很好的满足需求了,迫切需要一个更为强大,方便管理,集群部署的作业调度框架. 二:介绍 Quartz一个 ...
- C++类的运用 和 三大函数
在<数据结构与算法分析C++描述>一书中给出了三段代码,简单描述了C++类的接口.实现.与调用: #ifndef INTCELL_H_INCLUDED #define INTCELL_H_ ...
- tablet 的使用
之前一直用jbrowse 发现有些信息展示的不准确,如浏览一个bam文件的比对情况.在某一位点,深度为1000,但是浏览器显示的小于1000,并且read也经常会缺少.所以果断放弃jbrowse,用 ...
- sdut 2153 Clockwise (2010年山东省第一届ACM大学生程序设计竞赛)
题目大意: n个点,第i个点和第i+1个点可以构成向量,问最少删除多少个点可以让构成的向量顺时针旋转或者逆时针旋转. 分析: dp很好想,dp[j][i]表示以向量ji(第j个点到第i个点构成的向量) ...
- Open经验库网址
http://www.open-open.com/lib/view/open1436094840774.html