2

Well, I know this has been asked already and I also happen to know the easiest way to do so.

Now my question is more about your advice on if there is a better way.

I want my method to be called only once when the component is enabled or created. See I can create a component but keep it disabled, then when I enable it for the first time, I want the Init method to be called. The component is contained into an "attached" object.

So I have the Component with

internal bool _runOnce;

then I have the MainObject

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();
   }
}

My main concern is that the check for _runOnce will happen every frame for every component on each object. I know it is just a boolean check and is worth nothing but I am just asking if anyone would know a pattern for this purpose that is better than this.

Thanks

4

4 回答 4

2

您还可以列出仅启用的组件的列表....

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();
}
于 2013-10-04T18:04:19.993 回答
1

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 ...
}
于 2013-10-04T20:53:34.307 回答
1

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

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

探索诸如“ runonce Update()”之类的实现细节以了解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
 }
于 2013-10-04T18:29:39.700 回答
0

只是一个常规的 Component 构造函数呢?

public Component()
{
   Init();
}
于 2013-10-04T18:15:08.397 回答