2017-03-07 9 views
1

長い検索の後、私はここに来ることにしました。純粋にインターネット上のLuaで書かれたコンポーネントベースのエンティティシステムを見つけることは不可能でした。誰も私にLuaのコンポーネントベースエンティティシステムに関するサンプルコードを教えてもらえますか?

私はエンティティ - > "Player"を持っており、それにはHealthとWalkspeedが含まれています。 これらの2つのHealthとwalkspeedは、後にMonsterのような他のオブジェクトで使用できるコンポーネント自体を考慮しますか?私の理解は、コンポーネントは、後で異なるエンティティに追加できるメソッドとプロパティを持つ通常のテーブルに過ぎないということです。必要に応じて、ヘルスコンポーネントとスタミナコンポーネントの2つのコンポーネントを1つにまとめたり、マージすることができますか? 私が本当に望むのは、このシステムがどのように完全に機能するのか、最初の場所にコンポーネントが作成されるのか、どのようにエンティティなどに追加できるのか理解できないからです。 グローバル_Gテーブルに格納されているか、モジュールのまとまりとして格納されていますか? 私は、OOPと継承がどのようにluaで動作するのかを完全に理解していますが、コンポーネントベースのEntityシステムでは、ピクチャとダイアグラムのみのコード例はありません。

感謝:)

答えて

0

これら二つの記事:12は非常によく詳細にECS(エンティティコンポーネントシステム)を記述します。
これらを読んだら、LuaでECSを実装するのは簡単です。

「エンティティ」はテーブルです。キーはこのエンティティに属するコンポーネントタイプ名です。値はtrueです。

"コンポーネント"は一部のデータを含む単なるテーブルであり、一部のタイプのコンポーネントではテーブルが空の場合があります。

あなたが必要になります。

  • グローバルテーブル「All_Componentsを」:キーがコンポーネントのタイプ名で、値は、値がコンポーネント、
  • グローバルテーブル「All_Entities」(ある、キーはエンティティのIDである、サブテーブル、ありますキーはエンティティID、値はエンティティ)、
  • update()機能は論理的に順序付けられた「システム」のチェーンで構成されます(「システム」はコンポーネントの特定の組み合わせのコンポーネントを持つすべてのエンティティに対して何らかのアクションを実行するコードブロックです)タイプ)。

エンティティに新しいコンポーネントを追加することは、コンポーネントテーブルを作成し、All_ComponentsとAll_Entities内のいくつかのフィールドを変更することです。 > "プレーヤー" と、それは健康とWalkspeedが含まれています -


は私が実体を持っているとしましょう。これらの2つの健康とウォークスピードは、例えばMonsterのような他のオブジェクトで後で使用できるコンポーネント自体を考慮していましたか?

コンポーネントは、エンティティのプライベートデータです。
別のエンティティのコンポーネントの別のインスタンスを作成する必要があります。

All_Entities = { 
    [100] = { Health = true, Velocity = true, .... }, -- Player 
    [101] = { Health = true, Velocity = true, .... }, -- Monster 
    .... 
} 

All_Components = { 
    Health = { 
     [100] = { max_hp = 42, current_hp = 31 }, -- Player's health 
     [101] = { max_hp = 20, current_hp = 20 }, -- Monster's health 
     .... 
    }, 
    Velocity = { 
     [100] = { max_speed = 1.0, speed_x = 0, speed_y = 0 }, -- Player 
     [101] = { max_speed = 2.5, speed_x = -2.5, speed_y = 0 }, -- Monster 
     .... 
    }, 
    .... 
} 

function update(dt) 
    .... 
    -- "Health system" will act on all entities having "Health" component 
    for entity_id, component in pairs(All_Components.Health) do 
     -- 5 minutes for full regeneration 
     component.current_hp = math.min(
     component.max_hp, 
     component.current_hp + component.max_hp * dt/(5*60) 
    ) 
    end 
    .... 
    -- "Health_Bar system" will traverse over all the entities 
    -- having both Health and Health_Bar components simultaneously 
    for entity_id, comp_Health_Bar in pairs(All_Components.Health_Bar) do 
     local comp_Health = All_Components.Health[entity_id] 
     if comp_Health then 
     -- entity "entity_id" has two components: 
     -- comp_Health and comp_Health_Bar 
     -- Now we have all the info needed to draw its health bar 
     .... 
     end 
    end 
    .... 
end 

ここにOOPはありません。ECSはOOPとは関係ありません。

もちろん、ここでOOPを追加すると、同じ種類のすべてのコンポーネントをあるクラスのインスタンスとして扱うことができます。しかし本当にそれが必要ですか?
ECSの考え方:「コンポーネント」は生データであり、すべてのコードは「システム」内にあります。このアプローチはOOPよりも柔軟です。


は、二つの成分を一緒に添加したり、必要に応じて、一つに例の健康成分とスタミナコンポーネントにマージすることができますか?

「システム」によっては、これらのコンポーネントに異なるタイプが必要な場合があります。そのため、それらを分けておく方がよいでしょう。

+0

ありがとうございます。非常に役に立ちます:) –

+0

もう1つ質問があります。 「Health_Bar」コンポーネントがどのように「Health」コンポーネントから値を取得し、Health_Barサイズを「Health_Bar」コンポーネントに表示するかによって、3Dユーザーインターフェイス要素を保持するコンポーネント「Health_Bar」と、current_health、max_healthプロパティを保持する「Health」コンポーネントがあるとしましょう。 Health "コンポーネントの値。私は彼らが別々のコンポーネント "Health"と "Health_Bar"であることを望みます。なぜなら、私は各EntityにHealth_Barを表示したくないからです。 –

+0

** HealthとHealth_Barの両方のコンポーネントを同時に持つすべてのエンティティを同時にスキャンする新しい「システム」を追加する必要があります。答えに "Health Bar system"のコード例を追加しました。 –

関連する問題