【发布时间】:2019-06-20 16:49:44
【问题描述】:
使用实体-组件-系统模式我想将一些系统与事件联系起来。所以有些系统不应该循环运行,它们应该按需运行。
以 Health 系统为例,Death 系统应仅在组件的健康状况低于 1 时运行。
我曾想过拥有两种类型的系统。第一种是周期系统。每帧运行一次,例如 Render 或 Movement 系统。另一种类型是基于事件的系统。如前所述,健康和死亡之间的联系。
首先我创建了两个系统类型都使用的基本接口。
internal interface ISystem
{
List<Guid> EntityCache { get; } // Only relevant entities get stored in there
ComponentRequirements ComponentRequirements { get; } // the required components for this system
void InitComponentRequirements();
void InitComponentPools(EntityManager entityManager);
void UpdateCacheEntities(); // update all entities from the cache
void UpdateCacheEntity(Guid cacheEntityId); // update a single entity from the cache
}
我进一步创建了接口
internal interface IReactiveSystem : ISystem
{
// event based
}
和
internal interface IPeriodicSystem : ISystem
{
// runs in a loop
}
但我不确定它们是否有必要。使用没有问题
foreach (ISystem system in entityManager.Systems)
{
system.UpdateCacheEntities();
}
但如果不需要,我不想运行系统。
有两种类型的事件,ChangeEvent 和 ExecuteEvent。第一个在组件中的值发生更改时触发。当应该对特定实体执行某些操作时,会触发第二个。
如果你需要或想要你可以看看EntityManager
ComponentRequirements
以及ECS的使用
一个示例系统是这样的
internal class HealthSystem : IReactiveSystem
{
public HealthSystem(EntityManager entityManager)
{
InitComponentRequirements();
InitComponentPools(entityManager);
}
private Dictionary<Guid, HealthComponent> healthComponentPool;
public List<Guid> EntityCache { get; } = new List<Guid>();
public ComponentRequirements ComponentRequirements { get; } = new ComponentRequirements();
public void InitComponentRequirements()
{
ComponentRequirements.AddRequiredType<HealthComponent>();
}
public void InitComponentPools(EntityManager entityManager)
{
healthComponentPool = entityManager.GetComponentPoolByType<HealthComponent>();
}
public void UpdateCacheEntities()
{
for (int i = 0; i < EntityCache.Count; i++)
{
UpdateCacheEntity(EntityCache[i]);
}
}
public void UpdateCacheEntity(Guid cacheEntityId)
{
Health healthComponent = healthComponentPool[cacheEntityId];
healthComponent.Value += 10; // just some tests
// update UI
}
}
如何为不同的系统创建ChangeEvents 和ExecuteEvents?
编辑
有没有办法向组件添加事件委托,以便在更改事件正在侦听时为该实体运行特定系统,或者在执行事件正在侦听时按需运行?
提到ChangeEvent 和ExecuteEvent 我只是指事件代表。
目前我可以做这样的事情
internal class HealthSystem : IReactiveSystem
{
//… other stuff
IReactiveSystem deathSystem = entityManager.GetSystem<Death>(); // Get a system by its type
public void UpdateCacheEntity(Guid cacheEntityId)
{
// Change Health component
// Update UI
if(currentHealth < 1) // call the death system if the entity will be dead
{
deathSystem.UpdateCacheEntity(cacheEntityId);
}
}
}
但我希望通过使用事件委托使系统相互通信和共享数据来实现更好的架构。
【问题讨论】:
-
您的项目中是否使用了 IoC 容器?
-
对不起,什么是 IoC?但是不,我没有:)
-
IoC 是控制反转,它是一种编程范式,负责从您的程序中删除依赖项。在这里广泛描述:stackoverflow.com/questions/3058/what-is-inversion-of-control :)
-
这个问题应该因为过于宽泛而被关闭。你能把它缩小到一个特定的问题吗? “我如何设计我的应用程序”不是一个可以回答的问题。
-
@totalBeginner 不,它没有,因为我不知道(a)你想做什么,(b)你尝试了什么,(c)什么不起作用和(d)您遇到的确切错误消息或问题。简单地说你想使用事件委托是不够的。将它们用于什么,在什么情况下,实现什么?
标签: c# entity-component-system