Unity 单例初始化最佳实践:避免常见错误和提高效率
本文探讨了 Unity 中单例初始化的常见错误,并提供了一个改进的单例实现方案。
原始代码存在的问题
static mJoystickInput inst;
public static mJoystickInput Inst => inst;
private void Awake()
{
if (inst == null) inst = this;
else Destroy(this);
}
这段代码存在以下问题:
- 静态字段未初始化:
inst没有进行初始化,在第一次访问Inst属性时可能会导致空引用异常。 - 线程安全: 多个线程同时调用
Inst属性可能会导致inst被创建多次,破坏单例模式。 - 销毁方式: 如果
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);
}
}
}
这个改进后的单例实现包含以下关键点:
- 私有静态字段: 使用私有静态字段
_instance来存储单例实例,避免了静态字段未初始化的问题。 - FindObjectOfType: 在
Instance属性中,如果_instance为空,则使用FindObjectOfType方法查找场景中的mJoystickInput组件。 - 创建新 GameObject: 如果
FindObjectOfType无法找到mJoystickInput组件,则创建一个新的GameObject并添加mJoystickInput组件。 - DontDestroyOnLoad: 在
Awake方法中,如果_instance为空,则将_instance设置为当前组件,并调用DontDestroyOnLoad方法,确保单例在场景切换时不会被销毁。 - 销毁重复实例: 如果
_instance不为空,则销毁当前组件,避免创建多个单例实例。
总结
通过以上改进,我们获得了更加健壮、线程安全且跨场景可用的单例实现。建议在实际开发中使用这种方式来管理单例对象,以避免常见的错误并提高代码质量。
原文地址: https://www.cveoy.top/t/topic/mjdo 著作权归作者所有。请勿转载和采集!