這兩篇文章:1,2詳細描述ECS(實體 - 組件 - 系統)非常好。
閱讀完它們後,很容易在Lua中實施ECS。
「實體」是一個表:鍵是屬於此實體的組件類型名稱,值爲true
。
「組件」只是包含某些數據的表,對於某些類型的組件,該表可能爲空。
你將需要:
- 全局表「All_Components」:關鍵是組件類型名稱,值是子表,其中鍵是實體ID,值是組件,
- 全局表「All_Entities」(鍵是實體ID,值是實體),
- 您的
update()
函數將由「系統」的邏輯上有序的鏈組成(「系統」是代碼塊,用於對具有組件的某些特定組合的所有實體執行某些操作的代碼塊類型)。
將新組件添加到實體只是創建組件表並修改All_Components和All_Entities中的某些字段。
可以說我有實體 - > 「播放器」,它包含健康和Walkspeed。這兩個健康和步行者是否會考慮組件本身,以後可以用於其他物體,比如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更靈活。
可以兩種組分可以一起添加或合併的例如衛生成份和耐力組分合爲一體,如果需要的話?
某些「系統」將需要這些組件具有不同類型,因此最好將它們分開。
非常感謝你的這個,這是非常有幫助的:) –
我還有一個問題。假設我擁有僅保存current_health,max_health屬性的「健康」組件,然後保存具有3D用戶界面元素的組件「Health_Bar」,現在「Health_Bar」組件將如何從「健康」組件獲取值並顯示Health_Bar大小,依據「健康「組件值。我希望他們是單獨的組件「健康」和「Health_Bar」,因爲我不想在每個實體上顯示Health_Bar。 –
您應該添加新的「系統」,該系統同時遍歷具有** Health和Health_Bar組件的所有實體。我已將「Health Bar system」的代碼示例添加到答案中。 –