缓存 属性 (get) vs lazy initialization to safely GetComponent before awake in unity (mobile platforms)
Cache property (get) vs lazy initialization to safely GetComponent before awake in unity (mobile platforms)
- 我需要在启动时缓存大量组件(而且我不能直接在 monobehaviour 中引用它们)
- 我不确定它们何时会被请求(因此我无法将它们缓存在 Awake 中,因为它们可能会从另一个 Monobehaviour 的 Awake 中请求)
我最初的解决方案是使用 public get 属性,这是我更熟悉的模式。但现在我正在尝试延迟初始化(更具可读性)。
获取组件 属性
// --------------- COMPONENT AS PROPERTY --------------- //
private ComponentRequired _componentAsProperty;
private ComponentRequired _ComponentAsProperty
{
get
{
if (_componentAsProperty == null)
_componentAsProperty = GetComponentInChildren<ComponentRequired>(true);
return _componentAsProperty;
}
}
懒惰地检索组件
// --------------- COMPONENT AS LAZY --------------- //
private Lazy<ComponentRequired> _componentAsLazy
=> new Lazy<ComponentRequired>(GetComponentInChildren<ComponentRequired>(true));
我还阅读了 Cached property vs Lazy<T>(与实例化相关),同样的答案可能适用于组件的惰性检索。
在性能方面,我目前在分析器上没有发现很大的差异,但我想问一下以确保统一和组件(尤其是移动平台)可能存在的任何缺点。
Unity最好避免Lazy实现,因为它可以移出主线程(而GetComponent不能在主线程外使用)
unity 2019.1.7这个版本,使用properties来缓存任何组件都安全多了。
作为对答案的补充说明,带空检查的缓存 属性 不会节省太多性能,因为 Unity 引擎将不得不访问 C++ 对象以检查 GameObject 是否被销毁。您可以通过引入 bool 标志来显着提高性能。
private ComponentRequired _componentAsProperty;
private bool _componentInitialized;
private ComponentRequired _ComponentAsProperty
{
get
{
if(_componentInitialized) return _componentAsProperty;
_componentAsProperty = GetComponentInChildren<ComponentRequired>(true);
_componentInitialized = true;
return _componentAsProperty;
}
}
当组件可能不存在且 _componentAsProperty 保持为空时,这尤其重要。当然,如果这些组件是稍后创建的,这将不起作用。在这种情况下,子组件可以在 Awake() 期间使用 GetComponentInParent 进行注册。
另请注意,如果 gameObject 在缓存组件后被销毁,此方法仍然可以 return 非空 C# 对象。调用者必须执行空检查以确保游戏对象仍然存在。
- 我需要在启动时缓存大量组件(而且我不能直接在 monobehaviour 中引用它们)
- 我不确定它们何时会被请求(因此我无法将它们缓存在 Awake 中,因为它们可能会从另一个 Monobehaviour 的 Awake 中请求)
我最初的解决方案是使用 public get 属性,这是我更熟悉的模式。但现在我正在尝试延迟初始化(更具可读性)。
获取组件 属性
// --------------- COMPONENT AS PROPERTY --------------- //
private ComponentRequired _componentAsProperty;
private ComponentRequired _ComponentAsProperty
{
get
{
if (_componentAsProperty == null)
_componentAsProperty = GetComponentInChildren<ComponentRequired>(true);
return _componentAsProperty;
}
}
懒惰地检索组件
// --------------- COMPONENT AS LAZY --------------- //
private Lazy<ComponentRequired> _componentAsLazy
=> new Lazy<ComponentRequired>(GetComponentInChildren<ComponentRequired>(true));
我还阅读了 Cached property vs Lazy<T>(与实例化相关),同样的答案可能适用于组件的惰性检索。
在性能方面,我目前在分析器上没有发现很大的差异,但我想问一下以确保统一和组件(尤其是移动平台)可能存在的任何缺点。
Unity最好避免Lazy实现,因为它可以移出主线程(而GetComponent不能在主线程外使用)
unity 2019.1.7这个版本,使用properties来缓存任何组件都安全多了。
作为对答案的补充说明,带空检查的缓存 属性 不会节省太多性能,因为 Unity 引擎将不得不访问 C++ 对象以检查 GameObject 是否被销毁。您可以通过引入 bool 标志来显着提高性能。
private ComponentRequired _componentAsProperty;
private bool _componentInitialized;
private ComponentRequired _ComponentAsProperty
{
get
{
if(_componentInitialized) return _componentAsProperty;
_componentAsProperty = GetComponentInChildren<ComponentRequired>(true);
_componentInitialized = true;
return _componentAsProperty;
}
}
当组件可能不存在且 _componentAsProperty 保持为空时,这尤其重要。当然,如果这些组件是稍后创建的,这将不起作用。在这种情况下,子组件可以在 Awake() 期间使用 GetComponentInParent 进行注册。
另请注意,如果 gameObject 在缓存组件后被销毁,此方法仍然可以 return 非空 C# 对象。调用者必须执行空检查以确保游戏对象仍然存在。