Unity 单例模式

Unity中单例模式是非常常用的写法,可以基于C#语言的几种不同方法来实现。
下面我将列出几种常见的实现方式:

1. 经典的单例模式

public class SingletonExample : MonoBehaviour
{
    private static SingletonExample instance;
    public static SingletonExample Instance
    {
        get
        {
            if (instance == null)
            {
                instance = FindObjectOfType<SingletonExample>();
                if (instance == null)
                {
                    GameObject obj = new GameObject("SingletonExample");
                    instance = obj.AddComponent<SingletonExample>();
                    DontDestroyOnLoad(obj);
                }
            }
            return instance;
        }
    }
    
    private void Awake()
    {
        if (instance == null)
        {
            instance = this;
            DontDestroyOnLoad(this.gameObject);
        }
        else if (instance != this)
        {
            Destroy(gameObject);
        }
    }
}

优点:

  • 易于理解和实现。
  • 可以在Unity的场景中直接使用,提供了与Unity生命周期事件的结合。

缺点:

  • 不是完全的线程安全。在多线程环境下,可能会创建多个实例。
    如果没有在场景中找到实例,它会创建一个新的GameObject,这可能会导致意外的副作用。

2. 使用静态构造函数

public class SingletonExample
{
    private static readonly SingletonExample instance = new SingletonExample();

    static SingletonExample()
    {
    }

    private SingletonExample()
    {
    }

    public static SingletonExample Instance
    {
        get
        {
            return instance;
        }
    }
}

优点:

  • 实现简单,线程安全由CLR (公共语言运行时)保证。
  • 静态构造函数只会被执行一次,保证了实例的唯一性。

缺点:

  • 实例在程序运行时立即创建,无论是否使用,可能会导致资源的浪费。
    不适合在Unity场景对象中使用,因为它与MonoBehaviour断开了联系,不能直接应用到GameObject上。

3. 使用Lazy类型确保线程安全

using System;

public class SingletonExample
{
    private static readonly Lazy<SingletonExample> lazy =
        new Lazy<SingletonExample>(() => new SingletonExample());

    public static SingletonExample Instance { get { return lazy.Value; } }

    private SingletonExample()
    {
    }
}

优点:

  • 实现简单,线程安全由CLR (公共语言运行时)保证。
  • 静态构造函数只会被执行一次,保证了实例的唯一性。

缺点:

  • 实例在程序运行时立即创建,无论是否使用,可能会导致资源的浪费。
    不适合在Unity场景对象中使用,因为它与MonoBehaviour断开了联系,不能直接应用到GameObject上。

4. 双重校验锁(Double-Check Locking)

public class SingletonExample
{
    private static SingletonExample instance;
    private static readonly object lockObject = new object();

    public static SingletonExample Instance
    {
        get
        {
            if (instance == null)
            {
                lock (lockObject)
                {
                    if (instance == null)
                    {
                        instance = new SingletonExample();
                    }
                }
            }
            return instance;
        }
    }

    private SingletonExample()
    {
    }
}

优点:

  • 线程安全,并且在需要时才创建实例。
  • 相对于Lazy,在早期的.NET版本中也可以使用。

缺点:

  • 实现复杂,需要正确管理锁,否则可能会导致死锁。
  • 性能开销,每次访问实例时都需要进行双重检查。
  • 不直接与MonoBehaviour兼容,同样不适合直接应用于Unity场景中的对象。

总结:

在选择实现单例的方法时,应当考虑是否需要延迟初始化、是否在多线程环境中使用、以及是否需要与Unity的MonoBehaviour系统集成等因素。
在Unity中,经常使用第一种方法,因为它能够更好地与Unity的组件和生命周期集成。
不过,如果你在Unity项目中需要使用单例模式管理非MonoBehaviour类型的资源或类,例如数据管理或服务类,那么**第三种方法(Lazy)**是一个非常好的选择。

相关推荐

  1. Unity 模式

    2024-05-11 19:16:11       35 阅读
  2. 模式模板

    2024-05-11 19:16:11       43 阅读
  3. 模式【C#】

    2024-05-11 19:16:11       54 阅读
  4. python模式

    2024-05-11 19:16:11       63 阅读
  5. 模式详解

    2024-05-11 19:16:11       61 阅读
  6. 模式学习

    2024-05-11 19:16:11       48 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-11 19:16:11       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-11 19:16:11       106 阅读
  3. 在Django里面运行非项目文件

    2024-05-11 19:16:11       87 阅读
  4. Python语言-面向对象

    2024-05-11 19:16:11       96 阅读

热门阅读

  1. Centos安装 docker和docker-compose

    2024-05-11 19:16:11       32 阅读
  2. 机器学习_如何给客户做聚类K-Means

    2024-05-11 19:16:11       34 阅读
  3. SSL/TLS 协议

    2024-05-11 19:16:11       30 阅读
  4. thinkphp5.1 模型auto

    2024-05-11 19:16:11       25 阅读
  5. UnityDOTS备忘

    2024-05-11 19:16:11       27 阅读
  6. QT day2

    QT day2

    2024-05-11 19:16:11      26 阅读
  7. Qt宏和关键字

    2024-05-11 19:16:11       32 阅读
  8. SpringBoot 中检测文件编码格式

    2024-05-11 19:16:11       36 阅读
  9. SpringBoot 中 zip 文件解压工具类

    2024-05-11 19:16:11       32 阅读