如果你想让继承MonoBehaviour的类变成Singleten
2014-12-10 12:19
148 查看
单例是指只有一个实例的类
通常创建单例的方法是
下面的实现仅允许一个线程在尚未创建 Singleton 实例的情况下进入关键区域(该区域由 lock 块标识)。
下面是一个不使用Awake实现单例化并继承MonoBehavior的例子
using UnityEngine;
using System.Collections;
/// <summary>
/// MONOBEHAVIOR PSEUDO SINGLETON ABSTRACT CLASS
/// usage : best is to be attached to a gameobject but if not that is ok,
/// : this will create one on first access
/// example : '''public sealed class MyClass : Singleton<MyClass> {'''
/// references : http://tinyurl.com/d498g8c /// : http://tinyurl.com/cc73a9h /// : http://unifycommunity.com/wiki/index.php?title=Singleton /// </summary>
public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T _instance = null;
/// <summary>
/// gets the instance of this Singleton
/// use this for all instance calls:
/// MyClass.Instance.MyMethod();
/// or make your public methods static
/// and have them use Instance
/// </summary>
public static T Instance {
get {
if (_instance == null) {
_instance = (T)FindObjectOfType (typeof(T));
if (_instance == null) {
string goName = typeof(T).ToString ();
GameObject go = GameObject.Find (goName);
if (go == null) {
go = new GameObject ();
go.name = goName;
}
_instance = go.AddComponent<T> ();
}
}
return _instance;
}
}
/// <summary>
/// for garbage collection
/// </summary>
public virtual void OnApplicationQuit ()
{
// release reference on exit
_instance = null;
}
// in your child class you can implement Awake()
// and add any initialization code you want such as
// DontDestroyOnLoad(go);
// if you want this to persist across loads
// or if you want to set a parent object with SetParent()
/// <summary>
/// parent this to another gameobject by string
/// call from Awake if you so desire
/// </summary>
protected void SetParent (string parentGOName)
{
if (parentGOName != null) {
GameObject parentGO = GameObject.Find (parentGOName);
if (parentGO == null) {
parentGO = new GameObject ();
parentGO.name = parentGOName;
}
this.transform.parent = parentGO.transform;
}
}
}
通常创建单例的方法是
using System; public class Singleton { private static Singleton instance; private Singleton() {} public static Singleton Instance { get { if (instance == null) { instance = new Singleton(); } return instance; } } } 但是由于MonoBehaviour中不能用new,不能从一个构造函数初始化,所以上面这段代码要改写成 using System; public class Singleton :MonoBehavior { private static Singleton instance; public static Singleton Instance { return instance; } void Awake() { instance = this; } } 现在回过头来看通常方法有什么优点和缺点 优点 1.由于实例是在Instance属性方法内部创建的,因此类可以使用附加功能(例如,对子类进行实例化),即使它可能引入不想要的依赖性。 2.直到对象要求产生一个实例才执行实例化;这种方法称为“懒实例化”。懒实例化避免了在应用程序启动时实例化不必要的singleton。 缺点 在多线程环境下是不安全的。如果执行过程的不同线程同时进入Instance属性方法,那么可能会创建多个Singleton对象实例。 解决方法——静态初始化
public sealed class Singleton { private static readonly Singleton instance = new Singleton(); private Singleton(){} public static Singleton Instance { get { return instance; } } } 在此策略中,将在第一次引用类的任何成员时创建实例。 sealed阻止派生。 变量标记为readonly,意味着只能在静态初始化期间或在类构造函数中分配变量。 多线程Singleton
下面的实现仅允许一个线程在尚未创建 Singleton 实例的情况下进入关键区域(该区域由 lock 块标识)。
using System; public sealed class Singleton { private static volatile Singleton instance; private static object syncRoot = new Object(); private Singleton() {} public static Singleton Instance { get { if (instance == null) { lock (syncRoot) { if (instance == null) instance = new Singleton(); } } return instance; } } } http://msdn.microsoft.com/zh-cn/library/ff650316.aspx
下面是一个不使用Awake实现单例化并继承MonoBehavior的例子
using UnityEngine;
using System.Collections;
/// <summary>
/// MONOBEHAVIOR PSEUDO SINGLETON ABSTRACT CLASS
/// usage : best is to be attached to a gameobject but if not that is ok,
/// : this will create one on first access
/// example : '''public sealed class MyClass : Singleton<MyClass> {'''
/// references : http://tinyurl.com/d498g8c /// : http://tinyurl.com/cc73a9h /// : http://unifycommunity.com/wiki/index.php?title=Singleton /// </summary>
public abstract class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
private static T _instance = null;
/// <summary>
/// gets the instance of this Singleton
/// use this for all instance calls:
/// MyClass.Instance.MyMethod();
/// or make your public methods static
/// and have them use Instance
/// </summary>
public static T Instance {
get {
if (_instance == null) {
_instance = (T)FindObjectOfType (typeof(T));
if (_instance == null) {
string goName = typeof(T).ToString ();
GameObject go = GameObject.Find (goName);
if (go == null) {
go = new GameObject ();
go.name = goName;
}
_instance = go.AddComponent<T> ();
}
}
return _instance;
}
}
/// <summary>
/// for garbage collection
/// </summary>
public virtual void OnApplicationQuit ()
{
// release reference on exit
_instance = null;
}
// in your child class you can implement Awake()
// and add any initialization code you want such as
// DontDestroyOnLoad(go);
// if you want this to persist across loads
// or if you want to set a parent object with SetParent()
/// <summary>
/// parent this to another gameobject by string
/// call from Awake if you so desire
/// </summary>
protected void SetParent (string parentGOName)
{
if (parentGOName != null) {
GameObject parentGO = GameObject.Find (parentGOName);
if (parentGO == null) {
parentGO = new GameObject ();
parentGO.name = parentGOName;
}
this.transform.parent = parentGO.transform;
}
}
}
相关文章推荐
- 如果一个类是从MonoBehaviour继承,而迩又不把它放在场景的gameObject上,它的实例将会为空
- 如何不绑定脚本且不继承MonoBehaviour做U3D的开发
- MonoBehaviour继承类及其重要方法
- [置顶] 不继承MonoBehaviour的UI框架
- 【Unity】脚本没有继承MonoBehaviour 如何使用Destroy
- 在不继承MonoBehaviour的情况下单利的实现单利
- [Unity&接口]子类即继承接口类也继承MonoBehaviour的快速操作和重构实现
- Unity3D中继承MonoBehaviour的类中会被引擎自动调用的方法
- 继承MonoBehaviour的类是不可以实例化
- 关于继承MonoBehaviour的一些记录
- C#单例与继承MonoBehaviour的单例
- 如何不绑定脚本且不继承MonoBehaviour做U3D的开发
- Unity继承MonoBehaviour的静态单例
- 如何不绑定脚本且不继承MonoBehaviour做U3D的开发
- 如果可以后悔,世界会变成什么样
- 如果再不改变 你就变成了N年后的SB(转载)
- get_transform is not allowed to be called from a MonoBehaviour constructor (or instance field initia
- unity3d中脚本生命周期(MonoBehaviour lifecycle)
- MonoBehaviour介绍
- 【Unity编辑器扩展简介】在MonoBehaviour中可使用的编辑器扩展Attribute