谁能给我 Lua 中基于组件的实体系统的示例代码?
Can anyone give me example code about Component Based Entity System in Lua?
经过长时间的搜索我决定来这里,因为在互联网上找不到纯 Lua 编写的基于组件的实体系统。
假设我有实体--> "Player",它包含 Health 和 Walkspeed。
这两个 Health 和 walkspeed 本身是否会考虑组件,以便以后可以在其他对象(例如 Monster)中使用。我的理解是,组件只是常规的 tables,具有稍后可以添加到不同实体的方法和属性。如果需要,是否可以将两个组件添加到一起或合并,例如健康组件和耐力组件合二为一?
我真正想要的是示例代码,因为我不明白这个系统将如何完全工作,首先将如何创建组件,如何将它们添加到实体等......
另外,它们将如何存储在全局 _G table 中或作为模块块存储?
我完全理解 OOP 和继承在 lua 中的工作原理,但是基于组件的实体系统没有任何代码示例,只有图片和图表。
谢谢:)
这两篇文章:1, 2对ECS(Entity–Component–System)描述的很详细
阅读它们后,在 Lua 中实施 ECS 很容易。
一个"entity"是一个table:键是属于这个实体的组件类型名称,值是true
。
一个"component"只是一个包含一些数据的table,对于某些类型的组件,table可能是空的。
您将需要:
- global table "All_Components":key是组件类型名,value是subtable,其中key是实体ID,value是组件,
- global table "All_Entities"(键是实体ID,值是实体),
- 您的
update()
函数将由 "systems" 的逻辑顺序链组成("system" 是一个代码块,用于对具有组件的所有实体执行某些操作,这些实体具有组件的某些特定组合类型)。
向实体添加新组件只是创建组件table并修改All_Components和All_Entities中的一些字段。
Lets say i have entity--> "Player" and it contains Health and Walkspeed. Would these two Health and walkspeed considered components themselves that can later be used in other objects like Monster for example?
组件只是其实体私有的原始数据。
您应该为另一个实体创建另一个组件实例。
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,例如,将所有相同类型的组件视为某些class的实例。但你真的需要吗?
ECS的思路:"components"只是原始数据,所有代码都在"systems"里面,这种方式比OOP更灵活。
Can two components be added together or merged for example Health Component and Stamina component into one, if needed?
有些"systems"会需要这些组件有不同的类型,所以最好把它们分开。
经过长时间的搜索我决定来这里,因为在互联网上找不到纯 Lua 编写的基于组件的实体系统。
假设我有实体--> "Player",它包含 Health 和 Walkspeed。 这两个 Health 和 walkspeed 本身是否会考虑组件,以便以后可以在其他对象(例如 Monster)中使用。我的理解是,组件只是常规的 tables,具有稍后可以添加到不同实体的方法和属性。如果需要,是否可以将两个组件添加到一起或合并,例如健康组件和耐力组件合二为一? 我真正想要的是示例代码,因为我不明白这个系统将如何完全工作,首先将如何创建组件,如何将它们添加到实体等...... 另外,它们将如何存储在全局 _G table 中或作为模块块存储? 我完全理解 OOP 和继承在 lua 中的工作原理,但是基于组件的实体系统没有任何代码示例,只有图片和图表。
谢谢:)
这两篇文章:1, 2对ECS(Entity–Component–System)描述的很详细
阅读它们后,在 Lua 中实施 ECS 很容易。
一个"entity"是一个table:键是属于这个实体的组件类型名称,值是true
。
一个"component"只是一个包含一些数据的table,对于某些类型的组件,table可能是空的。
您将需要:
- global table "All_Components":key是组件类型名,value是subtable,其中key是实体ID,value是组件,
- global table "All_Entities"(键是实体ID,值是实体),
- 您的
update()
函数将由 "systems" 的逻辑顺序链组成("system" 是一个代码块,用于对具有组件的所有实体执行某些操作,这些实体具有组件的某些特定组合类型)。
向实体添加新组件只是创建组件table并修改All_Components和All_Entities中的一些字段。
Lets say i have entity--> "Player" and it contains Health and Walkspeed. Would these two Health and walkspeed considered components themselves that can later be used in other objects like Monster for example?
组件只是其实体私有的原始数据。
您应该为另一个实体创建另一个组件实例。
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,例如,将所有相同类型的组件视为某些class的实例。但你真的需要吗?
ECS的思路:"components"只是原始数据,所有代码都在"systems"里面,这种方式比OOP更灵活。
Can two components be added together or merged for example Health Component and Stamina component into one, if needed?
有些"systems"会需要这些组件有不同的类型,所以最好把它们分开。