これら二つの記事:1、2は非常によく詳細に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よりも柔軟です。
は、二つの成分を一緒に添加したり、必要に応じて、一つに例の健康成分とスタミナコンポーネントにマージすることができますか?
「システム」によっては、これらのコンポーネントに異なるタイプが必要な場合があります。そのため、それらを分けておく方がよいでしょう。
ありがとうございます。非常に役に立ちます:) –
もう1つ質問があります。 「Health_Bar」コンポーネントがどのように「Health」コンポーネントから値を取得し、Health_Barサイズを「Health_Bar」コンポーネントに表示するかによって、3Dユーザーインターフェイス要素を保持するコンポーネント「Health_Bar」と、current_health、max_healthプロパティを保持する「Health」コンポーネントがあるとしましょう。 Health "コンポーネントの値。私は彼らが別々のコンポーネント "Health"と "Health_Bar"であることを望みます。なぜなら、私は各EntityにHealth_Barを表示したくないからです。 –
** HealthとHealth_Barの両方のコンポーネントを同時に持つすべてのエンティティを同時にスキャンする新しい「システム」を追加する必要があります。答えに "Health Bar system"のコード例を追加しました。 –