如果你想让继承MonoBehaviour的类变成Singleten

单例是指只有一个实例的类

通常创建单例的方法是

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;
      }
  }
}

时间: 2024-10-10 18:14:02

如果你想让继承MonoBehaviour的类变成Singleten的相关文章

推送类服务大集合,如果你想开发推送的服务,可以参考下。

推送类的服务,开发者如果想开发推送类的,但又不知道如何选择,不知道哪个推送类的对自己的开发是否有利.devstore为你整合,汇集了上百种的第三方服务,这里为你分享一些推送类的服务.http://www.devstore.cn/service/serviceClassfiy/24.html推送类服务大集合,如果你想开发推送的服务,可以参考下.,布布扣,bubuko.com

多继承(虚继承)派生类对象内存结构

在这里谈一下虚继承.前面写过派生类对象的内存结构,都是基于VS2010编译器的,不同的编译器对于继承的处理不同,但本质都是一样的. 虚继承是解决共享基类问题的.例如在菱形继承中 如果不使用虚继承,基类A在D中会有两个,这不仅浪费内存,还会造成歧义.使用虚继承就可以解决基类共享的问题. 要想在派生类中共享基类(例如在D对象中只有一个A对象,这时候D对象中的B对象和C对象都可以查找到A,而不是在B对象和C对象中各含有一个A对象). 先看下面一个例子: #include<iostream> usin

【python】-- 类的继承(新式类/经典类)、多态

继承 之前我们说到了类的公有属性和类的私有属性,其实就是类的封装,现在准备随笔的 是继承,是面向对象的第二大特性. 面向对象编程 (OOP) 语言的一个主要功能就是"继承".继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展. 通过继承创建的新类称为"子类"或"派生类",被继承的类称为"基类"."父类"或"超类",继承的过程,就是从一般到

OOP3(继承中的类作用域/构造函数与拷贝控制/继承与容器)

当存在继承关系时,派生类的作用域嵌套在其基类的作用域之内.如果一个名字在派生类的作用域内无法正确解析,则编译器将继续在外层的基类作用域中寻找该名字的定义 在编译时进行名字查找: 一个对象.引用或指针的静态类型决定了该对象的哪些成员是可见的,即使静态类型与动态类型不一致: 1 #include <iostream> 2 using namespace std; 3 4 class A{ 5 public: 6 // A(); 7 // ~A(); 8 ostream& print(ost

面向对象程序设计——抽象基类,访问控制与继承,继承中的类作用域,拷贝函数与拷贝控制

一.抽象基类 1)纯虚函数 和普通的虚函数不同,一个纯虚函数无须定义.我们通过在函数体的位置(即在声明语句的分号之前)书写=0就可以将一个虚函数说明为纯虚函数.其中,=0只能出现在类内部的虚函数声明语句处. 值得注意的是,我们也可以为纯虚函数提供定义,不过函数体必须定义在类的外部.也就是说,我们不能在类的内部为一个=0的函数提供函数体. 2)含有纯虚函数的类是抽象基类 含有(或者未经覆盖直接继承)纯虚函数的类是抽象基类.抽象基类负责定义接口,而后续的其他类可以覆盖该接口.我们不能直接创建一个抽象

【python】-- 类的多继承、经典类、新式类

继承知识点补充 在python还支持多继承,但是一般我们很少用,有些语言干脆就不支持多继承,有多继承,就会带来两个概念,经典类和新式类. 一.多继承 之前我们都是讲的单继承,那么什么是多继承呢?说白了,就是:子类可以继承多个父类,就叫多继承. class SchoolMember(object): #SchoolMember类 '''学校成员基类''' def tell(self): print("the schoolmeber is tell...") class School(ob

接口多继承自接口和接口是否可以继承自一般类的疑问?

接口是常量值和方法定义的集合.接口是一种特殊的抽象类. Java类是单继承的.classB Extends classA java接口可以多继承.Interface3 Extends Interface0, Interface1, interface-- 不允许类多重继承的主要原因是,如果A同时继承B和C,而B和C同时有一个D方法,A如何决定该继承那一个呢? 但接口不存在这样的问题,接口全都是抽象方法继承谁都无所谓,所以接口可以继承多个接口. 注意: 1)一个类如果实现了一个接口,则要实现该接口

C++的继承操作---基类指针访问派生类问题---基类成员恢复访问属性问题

#include "stdafx.h" #include <iostream> #include <algorithm> using namespace std; class Base { public: int num; virtual void func() { cout<<"Do something in Base"<<endl; } }; class Derived:private Base { public:

修改tt模板让ADO.NET C# POCO Entity Generator With WCF Support 生成的实体类继承自定义基类

折腾几天记载一下,由于项目实际需要,从edmx生成的实体类能自动继承自定义的基类,这个基类不是从edmx文件中添加的Entityobject. 利用ADO.NET C# POCO Entity Generator With WCF Support生成的tt文件(比如model.tt)中找到 partial class partial class 修改tt模板让ADO.NET C# POCO Entity Generator With WCF Support 生成的实体类继承自定义基类