缓存 属性 (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)

我最初的解决方案是使用 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# 对象。调用者必须执行空检查以确保游戏对象仍然存在。