Unity基础之单例:单例脚本、单例模板

目录

1.单件脚本,需提前挂载到场景内

2.自动挂载,跨场景不销毁(尽量不要挂载多个)

3.单例模板类,泛型单例

4.测试


1.单件脚本,需提前挂载到场景内

using UnityEngine;
using System.Collections;

public class SingletonA : MonoBehaviour {
    //第一种单例:单件脚本
    public static SingletonA Instance{get;private set;}
    void Awake()
    {
        Instance = this;
    }
    public  void Test()
    {
        print("SingletonA");    
    }
}

2.自动挂载,跨场景不销毁(尽量不要挂载多个)

using UnityEngine;
/// <summary>
/// singleton 不需要手动拖拽给游戏物体
/// </summary>
public class SingletonB : MonoBehaviour
{
    private static SingletonB instance;
    public static SingletonB Instance
    {
        get
        {
            if (instance == null)
            {
                SingletonB[] sts = FindObjectsOfType<SingletonB>();
                if (sts.Length > 0)
                {
                    for (int i = 0; i < sts.Length; i++)
                    {
                        Debug.LogWarning(sts[i].gameObject.name + " is already Added SingletonB");
                        Destroy(sts[i]);
                    }
                }
                GameObject obj = new GameObject("B");
                instance = obj.AddComponent<SingletonB>();
                DontDestroyOnLoad(obj);//跨场景不销毁游戏物体
            }
            return instance;
        }
    }
    public void Test()
    {
        print("SingletonB");
    }
}

3.单例模板类,泛型单例

using UnityEngine;
using System.Collections;
/// <summary>
/// 单例模板类
/// </summary>
public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    private static T instance;
    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                GameObject obj = new GameObject();
                obj.name = typeof(T).Name + "<Singleton>";
                instance = obj.AddComponent<T>();
                DontDestroyOnLoad(obj);
            }

            return instance;
        }
    }
}

使用方法,例如音乐管理类

using UnityEngine;
using System.Collections;

[RequireComponent(typeof(AudioSource))]//如果没有组件添加组件
public class MusicManager : Singleton<MusicManager>
{
    private AudioSource _audio;//音乐播放器
    private AudioClip music;//背景音乐
    private bool isInitialized;//表示是否初始化
    void Init()
    {
        _audio = GetComponent<AudioSource>();
        music = Resources.Load("bg") as AudioClip;
        _audio.clip = music;
        isInitialized = true;
    }
    public void Play()
    {
        if (!isInitialized)
        {
            Init();
        }
        _audio.Play();
    }
}

4.测试

A需要提前挂载,B和音乐管理类自动生成

using UnityEngine;
using System.Collections;

public class Test : MonoBehaviour {

	void Start () {
        SingletonA.Instance.Test();
        SingletonB.Instance.Test();

        MusicManager.Instance.Play();
	}
}

### 实现和使用事件 在 Unity 中,C# 事件可以用于创建响应式的交互逻辑。通过结合设计模式,能够构建更加模块化和可维护的代码结构[^1]。 对于事件的应用,在大型项目中推荐采用发布/订阅模式来解耦不同部分之间的依赖关系。这可以通过定义全局事件中心或者利用现有的消息传递框架完成。当某个特定条件满足时触发相应处理函数执行一系列操作: ```csharp using UnityEngine; public class EventManager : MonoBehaviour { public delegate void OnGameStartHandler(); public static event OnGameStartHandler OnGameStart; private void Start() { // 订阅者注册到该事件上 if (OnGameStart != null) OnGameStart(); } } ``` 上述子展示了如何声明一个简的游戏启动事件处理器,并允许其他脚本监听此事件以便于做出反应。 另外还可以基于Unity原生组件如Button按钮控件自带onClick属性作为UI交互入口点设置回调方法调用;或是开发一套完整的自定义事件分发体系支持更复杂的业务需求场景下的灵活配置与管理。 ### 模式的最佳实践 针对模式而言,根据是否继承 `MonoBehaviour` 类型分为两种情况讨论其具体实现方式[^2]。 #### 继承 MonoBehavior 的 如果希望保持对生命周期的支持以及方便挂载至场景节点,则应考虑如下做法: ```csharp using UnityEngine; public sealed class Singleton<T> : MonoBehaviour where T : Component { private static T _instance; public static T Instance { get; private set; } protected virtual void Awake(){ if (_instance == null){ _instance = this as T; Instance = _instance; DontDestroyOnLoad(gameObject); }else{ Destroy(gameObject); } } } // 使用示:MySingleton.cs public class MySingleton : Singleton<MySingleton>{} ``` 这段代码片段提供了一个通用模板供任何想要成为的游戏对象所继承。它确保了即使加载新场景也不会销毁当前存在的唯一实副本。 #### 不继承 MonoBehavior 的纯 C# 而对于不需要附加到GameObject上的服务层或工具类来说,可以直接按照传统意义上的静态成员变量加私有构造器的方式来进行编码: ```csharp public sealed class Test { private static readonly Lazy<Test> lazy = new Lazy<Test>(() => new Test()); public static Test SingTonle => lazy.Value; private Test(){} } ``` 这采用了延迟初始化特性(`Lazy`)使得资源分配尽可能晚发生从而提高性能效率的同时也简化了线程安全性的考量[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jack Yan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值