初始化方法只调用一次 c#

本文关键字:一次 方法 调用 初始化 | 更新日期: 2023-09-27 18:33:53

嗯,我知道这个问题已经被问过了,我也碰巧知道最简单的方法。

现在我的问题更多的是关于你关于是否有更好方法的建议。

我希望在启用或创建组件时仅调用一次我的方法。请参阅我可以创建一个组件但将其禁用,然后当我第一次启用它时,我希望调用 Init 方法。组件包含在"附加"对象中。

所以我有组件

internal bool _runOnce;

然后我有主对象

List<Component> _listComp = new List<Component>();
void Update(){
   foreach(Component c in _listComp){
      if(!c.enable)continue;
      if(c._runOnce){
          c.Init();
          c._runOnce = false;
      }
      c.Update();
   }
}

我主要担心的是,对_runOnce的检查将针对每个对象上的每个组件进行每一帧。我知道这只是一个布尔校验,一文不值,但我只是问是否有人会知道比这更好的模式。

谢谢

初始化方法只调用一次 c#

您还可以仅列出已启用的组件。

List<Component> _listEnabled = _listComp.Where(item => (item.enable == true));
foreach(Component c in _listEnabled ){
   if(c._runOnce){
      c.Init();           // if at all possible, _runOnce should be set to false
      c._runOnce = false; // IN THE OBJECT, after calling Init();
   }
   c.Update();
}

我会质疑Update()是否是Init()动态组件的合适生命周期设计。

似乎有一个名义上称为GameObject.ActivateComponent(AbstractComponent C)调用C.Init()的方法更有意义,AbstractComponent::Init调用OnInit,这是组件覆盖和实现的。 AbstractComponent::Init会进行_runonce检查并提前返回。这是一个方法调用,但它使代码更加抽象,并且如果您需要为"这是我第二次或以后初始化"提供钩子,则可以选择扩展为稍后具有OnReinitialize代码路径。(比如说,一个统计重置选项...

对于Update()来说,探测像"runonce"这样的实现细节来了解Component的初始化状态似乎绝对是错误的。

List<Component> _listComp = new List<Component>();
void Update(){
   foreach(Component c in _listComp){
  c.Update();
   }
}

抽象组件

 public bool Enable { get;set;}
 private bool _initialized = false;
 void Update(){
     if (!Enable) return;
     Init();
     OnUpdate();
 }
 protected virtual void OnUpdate()
 {
 // filled in by user script
 }
 private void Init()
 {
 if (_initialized) return;
 OnInit();
 _initialized = true;
 }
 protected virtual void OnInit()
 {
 // filled in by user script
 }

My main concern is that the check for _runOnce will happen every frame for every component on each object.

由此,我假设您经常打电话给Update。我担心的是组件的Update方法,它很可能比布尔检查贵得多。这就是所谓的微优化:你把很多精力放在根本不成问题的事情上。

但是,我建议封装初始化。您的MainObject不需要对此一无所知。 _runOnce应该是组件的私有成员,enable应该是属性(顺便说一句:_runOnce应该在某处初始化为 true)。每次启用组件时,您都可以检查_runOnce并在需要时调用初始化:

public class MyComponent
{
    private bool _isInitialized; // I think this is a better name than _runOnce
    private bool _enable;
    public bool Enable
    {
        get
        {
            return _enable;
        }
        set
        {
            if (_enable == value)
            {
                return;
            }
            if (value == true && !_isInitialized)
            {
                Init();
            }
            _enable = value;
        }
    }
    private void Init()
    {
        // initialization logic here ...
        _isInitialized = true;
    }
}

另一个想法是将初始化推迟到 Update 方法。这基本上是你已经拥有的,但在面向对象的设计中:

public void Update()
{
    if (_enable && !_isInitialized)
    {
        Init();
    }
    // update logic here ...
}

组件的常规构造函数呢?

public Component()
{
   Init();
}