Unity3D中可中途释放的单例

使用静态类,静态变量的坏处是从程序加载后就一直占用内存,想要释放比较麻烦,可是之前使用的单例,没有提供释放的方法,那是不是也同静态的一样直到程序结束菜释放?那单例的好处是什么?

所以此处在单例中加入了可释放的方法来方便释放单例。

用途是:

用此单例管理场景物体时,在不切换场景的前提下释放掉该单例以及挂在单例游戏物体下的子物体

using UnityEngine;

public abstract class SingleBhv<T> : IMono
where T:MonoBehaviour
{
private static T m_instance;
private static object locked;

public static void SetInstance(T instance)
{
m_instance = instance;
}

public static T Instance
{
get
{
if (m_instance == null)
{
m_instance = FindObjectOfType<T>();
}
if (m_instance == null)
{
m_instance = new GameObject("_"+typeof(T).ToString()).AddComponent<T>();
}
return m_instance;
}
set
{
m_instance = value;
}
}

public override void Init()
{
m_instance = this as T;
isInited = true;
}

/// <summary>
/// 释放掉
/// </summary>
public static void Destroy()
{
if (m_instance)
{
GameObject.Destroy(m_instance.gameObject);
}
}
}

public abstract class IMono : MonoBehaviour
{
public bool isInited;

protected virtual void Start()
{
if (!isInited)
{
Init();
}
}

public virtual void Init()
{
isInited = true;
}
}

非MonoBeheavier的单例

外部调用以下代码来释放:

XX.Instance = null;

GC.Collect();

或者使用Resources.UnloadUnusedAssets()来释放内存,有时比GC.Collect()更有用!

注意事项:

其他地方不要存放该类的实例,要用该类时就用XX.Instance

using UnityEngine;
/// <summary>
/// single struct
/// </summary>
/// <typeparam name="T"></typeparam>
namespace SingleInstance
{
public class SingleInstance<T> where T : new()
{
public static T m_instance ;
private static Object locked = new Object();

public static T GetInstance()
{
if (m_instance == null)
{
lock (locked)
{
if (m_instance == null)
{
m_instance = new T();
}
}
}
return m_instance;
}

public static T Instance
{
get
{
return GetInstance();
}
set
{
m_instance = value;
}
}
}
}

上述代码SingleBhv在使用过程中会有使用不够方便(每次直接调用单例的方法时,有可能还没初始化)和释放内存不及时的问题,所以修改如下:

修改后有两个初始化方法Initial和Init,两个的区别在于Initial是在实例一被创建时就执行,Init则延后到设置参数后调用Init时再执行

using UnityEngine;

public abstract class SingleBhv<T> : IMono
where T : MonoBehaviour
{
private static T m_instance;
private static object locked;
/// <summary>
/// 比Init方法之前检测
/// </summary>
public bool isInitialled;

public static void SetInstance(T instance)
{
m_instance = instance;
}

public static T Instance
{
get
{
if (m_instance == null)
{
m_instance = FindObjectOfType<T>();
InvokeInitial();
}
if (m_instance == null)
{
m_instance = new GameObject("_" + typeof(T)).AddComponent<T>();
InvokeInitial();
}
return m_instance;
}
set
{
m_instance = value;
}
}

private static void InvokeInitial()
{
if (m_instance != null)
{
var instance = m_instance as SingleBhv<T>;
if (!instance.isInitialled)
{
instance.Initial();
instance.isInitialled = true;
}
}
}

/// <summary>
/// 在Init之前调用,并且第一次使用Instance时直接调用,犹如构造函数
/// </summary>
public virtual void Initial(){}
/// <summary>
/// 不同于Initial方法,此方法可以等待Instance各属性初始化完成后再调用
/// </summary>
public override void Init()
{
m_instance = this as T;
InvokeInitial();
isInited = true;
}

/// <summary>
/// 释放掉
/// </summary>
public static void Destroy()
{
if (m_instance)
{
GameObject.Destroy(m_instance.gameObject);
Resources.UnloadUnusedAssets();
}
}
}

Unity3D中可中途释放的单例的更多相关文章

  1. C#中的简单工厂和单例

    下面首先来说说简单工厂 举个例子: 首先是父类 public abstract class Pizza { public abstract string Info(); } } 子类 public c ...

  2. SpringMVC中的controller默认是单例的原因

    http://lavasoft.blog.51cto.com/62575/1394669/ 1.性能 :单例不用每次new浪费资源时间. 2.不需要:一般controller中不会定义属性这样单例就不 ...

  3. QT中实现应用程序的单例化

    一介绍 通过编写一个QSingleApplication类,来实现Qt程序的单例化,原文的作者是在Windows Vista + Qt4.4 下实现的,不过应用在其他平台上是没问题的.(本文是我在ht ...

  4. java中你确定用对单例了吗?

    作为程序员这样的特殊物种来说,都掌握了一种特殊能力就是编程思想,逻辑比較慎重,可是有时候总会忽略到一些细节,比方我,一直以来总认为Singleton是设计模式里最简单的,不用太在意,然而就是由于这样的 ...

  5. Spring IoC 中的(Singleton)单例对象创建过程探索

    前言 之前将spring framework 源码导入了idea,后来折腾调试了一下,于是研究了一下最简单的singleton对象在spring中是如何创建的.这里所谓的简单,就是指无属性注入,无复杂 ...

  6. Java中反射和Unsafe破坏单例设计模式

    有如下单例模式设计代码: class Singleton { private String info = "HELLO SHIT"; private static Singleto ...

  7. 如何使用双重检查锁定在 Java 中创建线程安全的单例?

    这个 Java 问题也常被问: 什么是线程安全的单例,你怎么创建它.好吧,在Java 5之前的版本, 使用双重检查锁定创建单例 Singleton 时,如果多个线程试图同时创建 Singleton 实 ...

  8. iOS中FMDB的使用【单例】

    DYDB.h Objective-C 12345678910111213141516 #import <Foundation/Foundation.h> #import <FMDB/ ...

  9. springmvc中的controller是单例的

    今天发现spring3中的controller默认是单例的,若是某个controller中有一个私有的变量a,所有请求到同一个controller时,使用的a变量是共用的,即若是某个请求中修改了这个变 ...

随机推荐

  1. class命名

    常见class关键词: 布局类:header, footer, container, main, content, aside, page, section 包裹类:wrap, inner 区块类:r ...

  2. 四种主要网络IO虚拟化模型

    本文主要为大家简要介绍VMware.Redhat.Citrix.Microsoft主要虚拟化厂商使用的4种主要的虚拟化IO模型 (emulation.para-virtualization.pass- ...

  3. sql练习记录

    三表关联如果字段为0则表示是散客卡 select a.shop_id as id,b.shop_name,a.balance,a.point,(IF(a.card_type_id<>0,c ...

  4. JavaScript之Array类型

    1. 创建数组 var colors = new Array(); var colors = new Array(20); var colors = new Array("blue" ...

  5. WinForm 多窗体

    多窗体:一.首先要想到的问题是:1.哪个是主窗体问题:主窗体隐藏了,关闭其它窗体后,没有将主窗体显示/关闭,那么程序就关不上了 方法:用构造函数传值,将窗体传到另一个窗体中去 Form1: using ...

  6. discuz后台登陆 口令卡添加

    1.通过根目录文件admin.php 找到 $admincp->init(); 2.指向  dz/source/class/discuz/discuz_admincp.php 这个方法funct ...

  7. C# 模拟webform里面按钮的点击事件

    生成的html内容 <body> <form method="post" action="./Login.aspx" id="for ...

  8. free

    free是查看内存的命令 1             2                   3                4           5                61      ...

  9. 极光推送Jpush(v3)服务端PHP版本集成(V3版本只调用推送API)

    因为版本升级,极光推送的API也有了V3,功能也更丰富了,但是对于我们有的用户来说,我们还是只需要调用推送的API就够了. 下载了一份PHP服务端的SDK(下载地址:http://docs.jpush ...

  10. nginx 模块讲解

    1. 通用配置选项: --prefix=<path>          指定Nginx的安装路径,所有其他的路径都要依赖于该选项 --sbin-path=<path>     ...