本文探讨了 Unity 中单例初始化的常见错误,并提供了一个改进的单例实现方案。

原始代码存在的问题

static mJoystickInput inst;
public static mJoystickInput Inst => inst;
private void Awake()
{
    if (inst == null) inst = this;
    else Destroy(this);
}

这段代码存在以下问题:

  1. 静态字段未初始化: inst 没有进行初始化,在第一次访问 Inst 属性时可能会导致空引用异常。
  2. 线程安全: 多个线程同时调用 Inst 属性可能会导致 inst 被创建多次,破坏单例模式。
  3. 销毁方式: 如果 inst 已经被赋值,则销毁当前对象的方式不够优雅,容易引起混淆。

改进后的单例实现

为了解决这些问题,我们可以使用以下代码:

public class mJoystickInput : MonoBehaviour
{
    private static mJoystickInput _instance;

    public static mJoystickInput Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = FindObjectOfType<mJoystickInput>();
                if (_instance == null)
                {
                    GameObject go = new GameObject('mJoystickInput');
                    _instance = go.AddComponent<mJoystickInput>();
                }
            }
            return _instance;
        }
    }

    private void Awake()
    {
        if (_instance == null)
        {
            _instance = this;
            DontDestroyOnLoad(gameObject);
        }
        else
        {
            Destroy(gameObject);
        }
    }
}

这个改进后的单例实现包含以下关键点:

  1. 私有静态字段: 使用私有静态字段 _instance 来存储单例实例,避免了静态字段未初始化的问题。
  2. FindObjectOfType: 在 Instance 属性中,如果 _instance 为空,则使用 FindObjectOfType 方法查找场景中的 mJoystickInput 组件。
  3. 创建新 GameObject: 如果 FindObjectOfType 无法找到 mJoystickInput 组件,则创建一个新的 GameObject 并添加 mJoystickInput 组件。
  4. DontDestroyOnLoad: 在 Awake 方法中,如果 _instance 为空,则将 _instance 设置为当前组件,并调用 DontDestroyOnLoad 方法,确保单例在场景切换时不会被销毁。
  5. 销毁重复实例: 如果 _instance 不为空,则销毁当前组件,避免创建多个单例实例。

总结

通过以上改进,我们获得了更加健壮、线程安全且跨场景可用的单例实现。建议在实际开发中使用这种方式来管理单例对象,以避免常见的错误并提高代码质量。

Unity 单例初始化最佳实践:避免常见错误和提高效率

原文地址: https://www.cveoy.top/t/topic/mjdo 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录