Skip to content

DOTS Layer Data

Component

For all component, these should NOT be used as field: - Native Container: it has separated life span, not supporting query. And there are better alternatives. - Fixed Array: Dynamic Buffer is a better alternative. - Fixed Size String: string is not processed in any way in DOTS Layer. This field is often passed along to the Managed Layer. It should just stay in the Managed Layer instead.

Data Component

  • Data that changes frequently
  • Data with large value range
    public struct Position: IComponentData {
        public float3 Value;
    }
    

Tag Component

  • Classification that changes seldomly.
  • Low storage cost in chunk.
    public struct SoldierTag: IComponentData {
    }
    public struct AirplaneTag: IComponentData {
    }
    

Classification that are processed differently

[WithAll(typeof(SoldierTag))]
internal partial struct SoldierVelocityJob : IJobEntity {
    public float deltaTime;

    private void Execute(in Velocity velocity, ref Position position) {
        position = SoldierUtils.Move(position, velocity);
    }
}
[WithAll(typeof(AirplaneTag))]
internal partial struct AirplaneVelocityJob : IJobEntity {
    public float deltaTime;

    private void Execute(in Velocity velocity, ref Position position) {
        position = AirplaneUtils.Move(position, velocity);
    }
}

Entity count is high enough to warrant a tag. If not, use a Data Component instead, so that these entities stay in the same chunk and benefit from batch processing.

[WithAll(typeof(SoldierTag))]
internal partial struct SoldierVelocityJob : IJobEntity {
    public float deltaTime;

    private void Execute(in Velocity velocity, ref Position position) {
        if (velocity.Value > 10f) {
            position = VeryFastSoldierUtils.Move(position, velocity);
        } else {
            position = SoldierUtils.Move(position, velocity);
        }
    }
}

Shared Component

  • Low storage cost.
  • Data that changes seldomly.
  • Data with small value range. Each value should ideally bring in a proportionally large amount of entities.
    public enum Diplomacy {
        Ally,
        Neutral,
        Enemy
    }
    public struct DiplomacyStatus: ISharedComponentData {
        public enum Diplomacy Value;
    }
    
    Possible to query by value and process them differently
    var neutrals = SystemAPI.QueryBuilder()
        .WithAll<Diplomacy>()
        .Build();
    neutrals.SetSharedComponentFilter(new Diplomacy{Value = Diplomacy.Neutral});
    
    // declare war on all neutral provinces
    EntityManager.SetSharedComponent(neutrals, new Diplomacy{Value = Diplomacy.Enemy});
    // process all allies and enemies differently
    new AllyJob().ScheduleParallel(allies);
    new EnemyJob().ScheduleParallel(enemies);
    

Enableable Component

  • Classification that changes frequently
  • Enableable Component works by adding a bit-wise flags into the chunk. This flag is used to iterate a query inside a job. Changes happen during job execution is collected and write to this flag at the end of the job.
    public struct WillBeInvisibleTag: IEnableableComponent, IComponentData {
    }
    
    internal partial struct CullEntityJob : IJobEntity {
        public CameraInfo Camera;
    
        private void Execute(EnabledRefRW<WillBeInvisibleTag> invisible, in Bound2D bound) {
            invisible.ValueRW = CameraUtils.IsInsideBound(bound, Camera);
        }
    }
    
    Classification that bound to a component value
    public struct Health: IEnableableComponent, IComponentData {
        public int Value;
    }
    
    [WithChangeFilter(typeof(Health))]
    internal partial struct SetDeadJob : IJobEntity {
        private void Execute(EnabledRefRW<Health> isAlive, in Health health) {
            isAlive.ValueRW = health.Value > 0;
        }
    }
    
    var deadArmies = SystemAPI.QueryBuilder()
        .WithDisabled<Health>()
        .Build();
    
    If we have too many classifications, using Enableable Component instead of Tag will avoid chunk fragmentation.

Advance data structures

Dynamic Buffer

Asset Blob

Entity Linkage

Clean Up Component

Aspect

Native Containers in System