直接访问静态类还是缓存它?

时间:2014-09-22 13:46:59

标签: c# caching unity3d

我知道如果在运行时经常使用它,最好缓存一个组件。如果我将组件缓存为静态变量并在运行时访问它怎么样?让我举个例子:

public class AudioManager : MonoBehaviour
{
    public static AudioManager audioManager;

    void Awake()
    {
        audioManager = this;
    }
}

然后,如果我从另一个类访问它,我应该使用AudioManager.audioManager还是事先缓存它(在性能方面说话)?

P.S。如果有什么不清楚,请告诉我。

编辑:我想我不知道我对Singletons到底在做什么,但为了说清楚,这是一个关于性能的新手问题:

在Awake中

1)_audioManager = AudioManager.audioManager,然后在更新

中使用_audioManager.someVariable

VS

2)更新

中的AudioManager.audioManager.someVariable

2 个答案:

答案 0 :(得分:2)

您无需在任何情况下缓存自己的组件速度。访问本身时,组件不会支付性能损失。

您可能正在考虑的用例是缓存对其他组件或对象的访问,这样您就不必使用GetComponent或GetComponentWithChildren进行查找。这确实节省了时间,但这不是一个复杂的模式:只是在第一次遇到其他组件或游戏对象时进行查找,将其存储在此组件内的字段中,并且您很好:

 class Example: MonoBehavior
 {

     public GameObject _TargetCharacter;
     private Transform _cachedTransform;
     private Animator  _cachedAnimator;

     void Awake()
     {
      if (_TargetCharacter != null)
      {
          _cachedTransform = _TargetCharacter.transform;
          _cachedAnimator = _TargetCharacter.GetComponent<Animator>();
       }
     }


     void Update()
     {
         DoSomething (_cachedTransform, _cachedAnimator);
     }
 } 

GetComponent和GetComponentInChildren相对昂贵,你不想每帧都这样做。但是,直接访问设置为字段的内容并不昂贵,因此无需对其进行缓存。

使它成为Singleton:在这个上下文中,你需要创建一个不是Component的单独的类,并且让它成为单例 - 你不能阻止某人将许多给定的MonoBehavior附加到Unity编辑器,因此您不希望假设只有一个组件浮动。在AudioManager示例中,您必须假设许多不同的组件可能都在查看同一个AudioManager。

这是一个很好的例子comparing shared behavior using Singletons vs shared behavior in a static class。两种方式达到同一目的,优势和劣势略有不同。

更新响应OP的评论如下:

如果原始代码的要点是使用常见的Unity缓存技巧来提高速度,则不需要它。如果OP在下面的评论中建议将经理变成其他类可以调用的“服务提供者”,那么有两条路可走:

标准的统一技巧是将缓存行为添加到需要访问AudioManager的其他类中。例如:

class SomeOtherComponent: MonoBehavior
{
    AudioManager _manager;
    void Awake()
    {
    AudioManager[] AllAudioManagers = GetComponents<AudioManager>();
    if (AllAudioManagers.Count == 1)
        {
        _manager = AllAudioManagers[0];
        }
    else
        {
         throw new RuntimeError ("Expecting one (and only one) AudioManager in scene");
        } 
    }
}

或多或少地切换到正确的Singleton实现只需要在上面的Awake方法中获取样板并集中到单例类中,允许您替换它。

对于单一模式的扩展讨论,请尝试this book

答案 1 :(得分:0)

我遵循一个简单的规则,如果我要多次调用一个组件,超过5个,那么我将其缓存。同样的规则我适用于单身人士。如果只有一个电话,那么我只使用Singleton.getInstance()


你应该真正缓存什么

Unity组件,例如Transform

缓存Transform之类的东西的逻辑来自于查看文档。变换不是变量,而是属性,恰好包含getter和setter。这些对你来说是隐藏的,但这就是它的实现方式。该属性恰好用C或C ++编写。因此,这会降低您的性能。