如果你想让继承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

转载于:https://www.cnblogs.com/yushui/p/4155139.html

<think>嗯,用户的问题是在C#中让抽象继承自Unity的MonoBehaviour。首先,我需要确认用户的需求。他们可能在开发Unity游戏时,希望创建一个抽象基,这个基需要继承MonoBehaviour,以便利用Unity的生命周期方法,比如Start、Update等,同时作为抽象,要求派生实现某些特定方法。 首先,我需要回忆Unity中MonoBehaviour的基本用法。MonoBehaviour是Unity脚本的基,所有挂载到GameObject上的脚本都必须直接或间接继承它。抽象继承MonoBehaviour是可行的,但需要确保派生正确实现抽象方法。 然后,参考用户提供的引用内容,特别是引用[1]和引用[3],关于抽象和派生实现抽象方法的部分。抽象中的抽象方法必须在派生中实现,否则编译会出错。因此,在示例中,抽象需要声明抽象方法,比如抽象方法Initialize(),然后在具体子中实现它。 接下来,考虑到Unity的特殊性,比如生命周期方法。如果抽象需要处理Start或Awake方法,可能需要使用虚方法而不是抽象方法,以便子可以选择是否重写。例如,在抽象中定义一个虚方法protected virtual void OnInitialize(),然后在Start方法中调用它,子可以重写OnInitialize来添加自己的初始化逻辑。 另外,要注意Unity不允许将抽象直接挂载到GameObject上,因为无法实例化抽象。所以必须通过具体子来挂载。在示例中,用户可能需要一个具体的子如EnemyController,继承自抽象BaseEnemy,并实现抽象方法Attack(),同时重写虚方法OnInitialize()。 还需要考虑Unity的序列化问题,如果抽象中有需要Inspector中显示的字段,可以使用[SerializeField]属性。例如,在抽象中声明[SerializeField] protected int health;,这样子可以访问并在Inspector中调整该字段的值。 此外,用户可能希望了解如何结合泛型,比如引用[5]中的例子,但当前问题主要集中在抽象继承MonoBehaviour,可能暂时不需要泛型,但可以作为扩展点提到。 最后,需要验证示例代码的正确性,确保抽象正确继承MonoBehaviour,包含抽象方法和虚方法,子正确实现,并且可以挂载到游戏对象上运行。同时,要提醒用户抽象无法直接挂载,必须通过具体子实例化。</think>### 如何在C#中让抽象继承自Unity的MonoBehaviour #### 1. 核心实现原理 在C#中,抽象可以继承自`MonoBehaviour`,但需要满足以下条件: - **抽象方法必须由派生实现**:若抽象中包含抽象方法,所有派生必须通过`override`关键字重写[^1][^3] - **Unity的特殊限制**:抽象无法直接挂载到`GameObject`上,必须通过具体子实例化[^4] #### 2. 实现步骤与示例 ##### (1) 定义抽象基 ```csharp using UnityEngine; public abstract class BaseEnemy : MonoBehaviour { // 抽象方法:必须由子实现 public abstract void Attack(); // 虚方法:可选择性地重写 protected virtual void OnInitialize() { Debug.Log("Base initialization"); } [SerializeField] protected int health; // 可序列化字段 void Start() { OnInitialize(); // 调用初始化逻辑 } } ``` ##### (2) 实现具体子 ```csharp public class EnemyController : BaseEnemy { // 必须实现抽象方法 public override void Attack() { Debug.Log("Enemy launched attack"); } // 可选重写虚方法 protected override void OnInitialize() { base.OnInitialize(); // 调用基实现 health = 100; // 访问受保护字段 } } ``` #### 3. 关键注意事项 1. **生命周期方法处理**: - 若需要重写`Awake()`/`Start()`,建议定义为虚方法: ```csharp protected virtual void Start() { /*基逻辑*/ } ``` - 子通过`override`和`base.Start()`调用基实现[^3] 2. **接口与抽象结合**: ```csharp public interface IDamageable { void TakeDamage(int amount); } public abstract class Character : MonoBehaviour, IDamageable { public abstract void TakeDamage(int amount); // 接口实现 } ``` 3. **Unity编辑器集成**: - 通过`[Header("生命值")]`添加Inspector注释 - 使用`[RequireComponent(typeof(Rigidbody))]`添加组件依赖 #### 4. 应用场景 1. **游戏对象模板**:定义具有共同行为的敌人/NPC基 2. **UI系统**:创建可重用的UI控件基 3. **状态机**:实现状态模式的基础抽象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值