1

注:この紹介はエンティティシステムに関するものです。しかし、これらが何であるかを知らない場合、または自分で実装していない場合でも、それはかなり基本的なことであり、一般的なJavascriptの経験がある場合は、おそらく答えるのに十分すぎるほどの資格があります。

T=machineブログでエンティティシステムに関する記事を読んでいます。

著者のAdamは、エンティティはIDである必要があり、そのコンポーネント(つまり、エンティティが表すことになっている実際のデータ)を取得するために使用できると提案しています。

すべてのエンティティを「1か所」に保存するモデルを選択しました。このストレージを実装する主な疑いは、多くの人が使用する配列の配列アプローチです。これは、属するコンポーネントのインデックスを表す動的なエンティティIDを意味します。コンポーネントはその「1つの場所」(これからは単に「ストレージ」と呼びます)でタイプごとにグループ化されますが、これをとして実装する予定です。は、エンティティの構成、ストレージを処理し、エンティティ(など)に対していくつかの基本的な操作を実行できるオブジェクトになります。SceneScene.addComponent(entityID, component)

私はオブジェクトについて心配していませんScene、それが良いデザインであるとかなり確信しています、しかし私が確信していないのはストレージの実装です。

私には2つの選択肢があります:

A)ストレージが次のようになるアレイオブアレイアプローチを使用します。

//storage[i][j] - i denotes component type, while j denotes the entity, this returns a component instance
//j this is the entity id

[
    [ComponentPosition, ComponentPosition, ComponentPosition],
    [ComponentVelocity, undefined, ComponentVelocity],
    [ComponentCamera, undefined, undefined]
]

//It's obvious that the entity `1` doesn't have the velocity and camera components, for example.

B)ストレージオブジェクトをディクショナリ(技術的にはJavascriptのオブジェクト)として実装します

{
    "componentType": 
    {
        "entityId": ComponentInstance
    }
}

辞書のアプローチは、エンティティIDが静的であることを意味します。これは、エンティティシステム自体の外部でゲームループやその他の機能を実装するのに非常に良いことのようです。また、これは、システムが関心のあるエンティティIDの配列を簡単に格納できることを意味します。entityId変数も、明らかに整数インデックスではなく文字列になります。

配列の配列アプローチに反対する理由は、エンティティを削除すると、単一のエンティティが削除されたときに他のエンティティIDが変更されるためです。

実際の実装の詳細には注意が必要かもしれませんが、パフォーマンスの面でどちらのアプローチが優れているか知りたいですか?

私も興味を持っていること(可能な限りクロスプラットフォームにしてください。ただし、必要に応じて、例としてV8を使用してください)。

  • プロパティにアクセスするときのオーバーヘッドはどのくらいですか、そしてそれは蹄の下でどのように実装されていますか?ローカルスコープ内からアクセスしているとしましょう。
  • メモリには何がundefinedあり、どれくらいかかりますか?配列の配列アプローチでは、すべての内部配列が同じ長さである必要があり、エンティティに特定のコンポーネントがない場合、そのフィールドはに設定されるため、これを尋ねますundefined
4

1 に答える 1

-1

アレイについて心配する必要はありません。これはJavaScriptのオブジェクトです。つまり、「実際の」配列はありません。インデックスは、オブジェクトのプロパティ(辞書、ハッシュ、マップ)の数値の「名前」です。

考え方は単純です。配列には長さプロパティがあり、ループが反復を停止する場所を知ることができます。配列から要素を削除するだけで(これはオブジェクトであることを忘れないでください)、lengthプロパティは実際には変更されません。それで...

// create an array object
var array = ['one','two', 'three'];
console.log(array.length); // 3
// these don't actually change the length
delete array['two']; // 'remove' the property with key 'two'
console.log(array.length); // 3
array['two'] = undefined; // put undefined as the value to the property with key 'two'
console.log(array.length); // 3
array.splice(1,1); // remove the second element, and reorder
console.log(array.length); // 2
console.log(array); // ['one','three']
  1. JavaScriptが期待どおりに「機能」しないことを理解する必要があります。パフォーマンスに関しては、オブジェクトと配列は同じです。つまり、配列は辞書のようにアクセスされます。
  2. スコープは他の「cスタイル」言語とは異なります。グローバルスコープと関数スコープのみがあります。つまり、ブロックスコープはありません(for(var i)を別のfor(var i)内に記述しないでください)。
  3. メモリ内の未定義は、nullとまったく同じ量を取ります。違いは、nullは意図的な値の欠落であり、undefinedは単なる偶発的な(意図的ではない)欠落であるということです。
  4. if(array['two'])フィールドが実際にはundefined、null、0、 ""、falseの偽の値を保持し、falseと評価される可能性があるため、フィールドが存在するかどうかを確認しないでください。常にif('two' in array);で確認してください。
  5. for(key in array)常に使用してループするif(array.hasOwnProperty(key))場合は、プロトタイプのプロパティ(親のプロパティ)を繰り返さないようにします。また、コンストラクター関数によって作成されたオブジェクトは、「コンストラクター」キーでもループする可能性があります。
于 2012-07-21T20:39:42.970 に答える