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. reqwest请求api和约束(转载)

    转自:https://www.oschina.net/p/reqwest reqwest 用于浏览器异步HTTP请求.支持xmlHttpRequest, JSONP, CORS, 和 CommonJS ...

  2. js通过继承实现私有函数

    本文是原创文章,如需转载,请注明文章出处 主要思想就是在继承时,只开放共有的属性和方法,不开放另外某些函数,从而实现私有的作用. function A(){ this.x = 100; this.y ...

  3. css权值计算

    外部样式表<内部样式表<内联样式: HTML 标签选择器的权值为 1: Class 类选择器的权值为 10: ID 选择器的权值为 100: 内联样式表的权值最高 1000: !impor ...

  4. WAP站点(IIS/Apache)的服务器设置

    Server 端的设置IIS服务器:为了使IIS支持WAP(WML)页面的发布,在IIS的Web站点的属性 / HTTP信息中设置WAP的MIME属性,添加如下的MIME类型:扩展名 内容类型(MIM ...

  5. android事件拦截处理机制详解

    前段时间刚接触过Android手机开发,对它的事件传播机制不是很了解,虽然网上也查了相关的资料,但是总觉得理解模模糊糊,似是而非,于是自己就写个小demo测试了一下.总算搞明白了它的具体机制.写下自己 ...

  6. How to Develop blade and soul Skills

    How to Develop Skills Each skill can be improved for variation effects. Some will boost more strengt ...

  7. hdoj 1576

    //1Y真是爽啊 题意:要求(A/B)%9973,但由于A很大,我们只给出n(n=A%9973)(我们给定的A必能被B整除,且gcd(B,9973) = 1).  分析:根据题意a=b*x   a=m ...

  8. openssl

    openssl genrsa -des3 -out server.key 1024openssl req -new server.key -out servr.csr seserver-fnamese ...

  9. 第三篇:Retrofit SDK的设计思路

    2016-05-08 15:24:03 Retreofit毫无疑问是一个优美的开源框架,有轻量级.耦合性低.扩展性好.灵活性高的特点,那么Retrofit的设计者们到底是怎么样做到这些的呢?我希望能够 ...

  10. Bootstrap学习笔记(一)

    一.什么是Bootstrap bootstrap是一款css框架,便于响应式设计. 二.怎样使用bootstarp 最常用的方法,在html结构中引入样式表bootstarp.min.css,以及jq ...