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. composer 使用详解

    1,安装 php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" php -r &quo ...

  2. merge into在oracle10g和oracle 11g中的使用差别一

    oracle10g上的代码 MERGE INTO TCGGYSGHCP CP    USING (SELECT *             FROM (SELECT QD.LIFNR,         ...

  3. SPSS数据分析—判别分析

    判别分析作为一种多元分析技术应用相当广泛,和其他多元分析技术不同,判别分析并没有将降维作为主要任务,而是通过建立判别函数来概括各维度之间的差异,并且根据这个判别函数,将新加入的未知类别的样本进行归类, ...

  4. Scrapy爬虫导图(持续完善中)

    Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中.

  5. Linux(Ubuntu 14.04) setting up OpenGL

    1. Install c/c++ compilation package. 2. install openGL and freeGlut library sudo apt-get install me ...

  6. 面试中常用的__proto__,prototype和原型链,你都了解了吗?

    上一篇随笔主要讲了变量提升的问题,今天我们来讲讲很多前端er在初期很长一段时间内都没有完全搞明白的原型链和构造函数. 1,什么是构造函数 那么要讲到构造函数,必须要有一个函数,所以我们建立一个函数 f ...

  7. mysql自增主键归零的方法

    最近老是要为现在这个项目初始化数据,搞的很头疼,而且数据库的Id自增越来越大,要让自增重新从1开始:那么就用下面的方法吧:方法一: 如果曾经的数据都不需要的话,可以直接清空所有数据,并将自增字段恢复从 ...

  8. iOS 架构模式--解密 MVC,MVP,MVVM以及VIPER架构

    本文由CocoaChina译者lynulzy(社区ID)翻译 作者:Bohdan Orlov 原文:iOS Architecture Patterns 在 iOS 中使用 MVC 架构感觉很奇怪? 迁 ...

  9. ASP.NET MVC增删改查

    ASP.NET MVC中的增删改查 基本都要使用C控制器中的两个action来完成操作,一个用于从主界面跳转到新页面.同时将所需操作的数据传到新界面,另一个则对应新界面的按钮,用于完成操作.将数据传回 ...

  10. border家族

    border-style:dotted solid double dashed(上边框是点状,右边框是实线,下边框是双线,左边框是虚线)边框样式;border-width(边框宽度);border-r ...