2

ええと、これはすでに尋ねられていることを知っていますし、たまたま最も簡単な方法も知っています。

今、私の質問は、より良い方法があるかどうかについてのあなたのアドバイスについてです。

コンポーネントが有効化または作成されたときに、メソッドを 1 回だけ呼び出すようにしたい。コンポーネントを作成できますが、無効のままにしておくことができます。その後、初めて有効にするときに、Init メソッドを呼び出す必要があります。コンポーネントは「添付」オブジェクトに含まれています。

だから私はコンポーネントを持っています

internal bool _runOnce;

それから私は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();
   }
}

私の主な懸念は、_runOnce のチェックが、各オブジェクトのすべてのコンポーネントのすべてのフレームで発生することです。私はそれが単なるブールチェックであり、何の価値もないことを知っていますが、これよりも優れたこの目的のためのパターンを誰かが知っているかどうかを尋ねているだけです.

ありがとう

4

4 に答える 4

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と呼ばれるメソッドを持つ方が理にかなっているようです。_runonce チェックと早期復帰を行います。これはメソッド呼び出しですが、コードをより抽象化し、 「これは 2 回目以降に init された」ためのフックを提供する必要がある場合は、後でコード パスを持つように拡張するオプションがあります。(たとえば、統計リセットオプション...)OnInitAbstractComponent::InitOnReinitialize

Update()の初期化状態を調べるために「runonce」のような実装の詳細を調査するのは、明らかに間違っているようですComponent

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

AbstractComponent

 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

コンポーネントの通常のコンストラクタはどうですか?

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