How to setup Modules

Modules have the biggest difference between default Object based Unity and ECS. Instead of hosting the logic inside of the Module itself it is instead handled by a user implemented system. To setup Modules for Entities you must inherit from IEntityModule. Here is an example from the samples provided.

    public class DamageOverTimeModule : Module, IEntityModule
    {
        public void ModifyCommandBuffer(ref EntityCommandBuffer commandBuffer, in Entity entity, ModuleInstance moduleInstance)
        {
            DamageOverTimeInstance damageOverTimeInstance = moduleInstance as DamageOverTimeInstance;

            commandBuffer.AddComponent(entity, new DamageOverTimeEntityModule()
            {
                InvervalSeconds = damageOverTimeInstance.IntervalSeconds
            });
        }
    {
    
    public struct DamageOverTimeEntityModule : IComponentData
    {
        public float InvervalSeconds;
        public float CurrentSeconds; // For use in the ISystem
    }

When a new Status Effect is added to an Entity, it will add a burstable instance of any Modules as children of that Entity. There are many useful variables stored in the Module, and they can be used like this:

partial struct DamageOverTimeJob : IJobEntity
{
    public EntityCommandBuffer.ParallelWriter CommandBuffer;
    [ReadOnly]
    public ComponentLookup<ExamplePlayer> PlayerLookup;
    public float TimeDelta;

    public void Execute([ChunkIndexInQuery] int sortKey, ref DamageOverTimeEntityModule damageOverTime, in Module module)
    {
        Entity entity = module.Parent;
        
        if (PlayerLookup.TryGetComponent(entity, out ExamplePlayer player))
        {
            damageOverTime.CurrentSeconds -= TimeDelta;
            while (damageOverTime.CurrentSeconds <= 0)
            {
                damageOverTime.CurrentSeconds += damageOverTime.InvervalSeconds;
                player.Health -= module.BaseValue * module.Stacks;
                CommandBuffer.SetComponent(sortKey, entity, player);
            }
        }
    }
}

Note how in addition to querying for the custom DamageOverTimeEntityModule you can also get the base Module. The base Module has the following properties:

Name
Type
Description

Parent

Entity

The parent Entity reference.

BaseValue

float

Base value of the StatusEffectData.

Stacks

int

The current stack count.

PreviousStacks

int

The previous stack count.

IsBeingUpdated

bool

Whether the stack count was updated this frame.

IsBeingDestroyed

bool

Whether the StatusEffect was destroyed this frame.

Instead of querying the Module every frame, you could also include the ModuleUpdateTag or the ModuleDestroyTag in the query to only execute when those components are enabled. You could also just query for the ModuleUpdateTag and check the IsBeingDestroyed bool. This can lead to more performant Module systems.

Last updated