作者:王选易,出处: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)的更多相关文章

  1. 【Unity3D基础教程】给初学者看的Unity教程(四):通过制作Flappy Bird了解Native 2D中的RigidBody2D和Collider2D

    作者:王选易,出处:http://www.cnblogs.com/neverdie/ 欢迎转载,也请保留这段声明.如果你喜欢这篇文章,请点[推荐].谢谢! 引子 在第一篇文章[Unity3D基础教程] ...

  2. 【Unity3D基础教程】给初学者看的Unity教程(一):GameObject,Compoent,Time,Input,Physics

    作者:王选易,出处:http://www.cnblogs.com/neverdie/  欢迎转载,也请保留这段声明.如果你喜欢这篇文章,请点推荐.谢谢! Unity3D重要模块的类图 最近刚刚完成了一 ...

  3. Unity3D基础知识梳理

    这段时间在做Unity的项目,这差不多是我的第一次实战啊~然后公司来了实习的童鞋要学Unity,但是我一向不靠谱啊,所以只能帮他们稍微梳理下基础的东西了啊,唉~学长只能帮你们到这里了~顺便就把自己这两 ...

  4. Unity教程之再谈Unity中的优化技术

    这是从 Unity教程之再谈Unity中的优化技术 这篇文章里提取出来的一部分,这篇文章让我学到了挺多可能我应该知道却还没知道的知识,写的挺好的 优化几何体   这一步主要是为了针对性能瓶颈中的”顶点 ...

  5. i3D的一篇Unity教程中的笔记

    原地址:http://blog.sina.com.cn/s/blog_72b936d80100wwej.html 以下是i3D的一篇Unity教程中的笔记. i3D的这篇教程是[i3D.Next-Ge ...

  6. Nullsoft教程 NSIS初学者图文教程一

    Nullsoft教程 NSIS初学者图文教程一 来源:互联网 作者:佚名 时间:03-29 00:34:33 [大 中 小] Nullsoft Installation System(nsis) 是一 ...

  7. ios游戏开发 Sprite Kit教程:初学者 1

    注:本文译自Sprite Kit Tutorial for Beginners 目录 Sprite Kit的优点和缺点 Sprite Kit vs Cocos2D-iPhone vs Cocos2D- ...

  8. Sprite Kit教程:初学者

    作者:Ray Wenderlich 原文出处:点击打开链接 http://www.raywenderlich.com/42699/spritekit-tutorial-for-beginners 转自 ...

  9. 专门针对初学者的Node.js教程

    转载原文:http://www.csdn.net/article/2013-08-28/2816731-absolute-beginners-guide-to-nodejs Node.js的教程并不缺 ...

随机推荐

  1. 字符串常量演示Demo

    public class StringDemo { public static void main(String[] args) { // TODO Auto-generated method stu ...

  2. Python 安全类目推荐 (持续更新)

    推荐学习书目 › Learn Python the Hard Way › Python 学习手册 › Python Cookbook › Python 基础教程 Python Sites › PyPI ...

  3. 如何用JS判断网页中某个id的网页元素是否存在

    <meta http-equiv="content-type" content="text/html;charset=utf-8" /> <m ...

  4. Python入门(二,基础)

    一,基本语法 Python标识符 在python里,标识符有字母.数字.下划线组成. 在python中,所有标识符可以包括英文.数字以及下划线(_),但不能以数字开头. python中的标识符是区分大 ...

  5. Net作业调度-----Quartz.Net

    一:业务需求: 项目需要在不同时刻,执行一个或很多个不同的作业. Windows执行计划这时并不能很好的满足需求了,迫切需要一个更为强大,方便管理,集群部署的作业调度框架. 二:介绍 Quartz一个 ...

  6. SQUID之cache_peer

    一共关系到cache_peer/always_direct/never_direct/hierarchy_stoplist/prefer_direct等配置项. squid的使用指南上,关于alway ...

  7. 【转】阿里2015校招面试回忆(成功拿到offer)

    原文转自:http://blog.jobbole.com/78722/ 1. 引言 继上次<百度2015校园招聘面试题回忆(成功拿到offer)>文章过后,大家都希望除了题目之外,最好能给 ...

  8. VirtualBox 设置共享文件夹自动挂载

    1.在VirtualBox中设置文件夹位置和名称,这里使用的名称是share 1.在ubuntu12.04的/etc/rc.local中加入自动挂载命令 sudo mount -t vboxsf sh ...

  9. 让IE9支持html5

    IE10以上才算是真正支持了html5 ,但仍然有些地方和别的浏览器不一致,比如要在js里移除一个html标签, 如果是IE,document.getElementById("a" ...

  10. 神逸之作:国产快速启动软件神品ALTRun

    http://xbeta.info/altrun.htm 作者: ET民工和塞壬 日期: 2010-09-15 分类: windows 标签: quick-launch <神逸之作:国产快速启动 ...