Is There a More Efficient Approach to getting the state of multiple IEnableableComponent's?

Hi I’ve been working on a dungeon generator for a personal project of mine. As a part of this I made a system that generates a grid containing cells. each cell needs to have information on what type of cell it is. At first I started out with the CellTypeComponentData containing an enum, but soon realised I wanted to be able to filter queries based on the celltype. This is where flags like CellTypeIsEmpty come in. By making them IEnableableComponent, I avoid making structural changes whenever a type changes.

To make sure to set the data correctly I wrote an Aspect with a public method to set the data.
Now, I’m aware that this essentially creates the same data twice, but with a different representation (in Flag/Tag form and as a component with an enum).

Is there a better way to do this? I thought about getting rid of the CellTypeComponentData component, but I like the convenience of being able to look up the data without having to do multiple component checks on the entity.

Celltype

  public struct CellTypeComponentData : IComponentData
    {
        [SerializeField]
        public CellType value;
    }
    [Serializable]
    [Flags] public enum CellType
    {
        None = 0,
        Empty = 1,
        Room = 2,
        Hallway = 4,
        Space = 8,
           
    }
   
    // Flags that need to be empty. Implements IEnableableComponent to facilitate enable and unabling
    public struct CellTypeIsEmpty : IComponentData, IEnableableComponent {}
    public struct CellTypeIsRoom : IComponentData, IEnableableComponent {}
    public struct CellTypeIsHallway : IComponentData, IEnableableComponent {}
    public struct CellTypeIsSpace : IComponentData, IEnableableComponent {}

CellAspect

public readonly partial struct CellAspect : IAspect
    {
        public readonly Entity entity;
        public readonly RefRW<CellCoordinateComponentData> cellPositionComponent;
        public readonly RefRO<LocalTransform> localTransformComponent;
        private readonly EnabledRefRW<CellTypeIsEmpty> cellTypeIsEmptyFlag;
        private readonly EnabledRefRW<CellTypeIsHallway> CellTypeIsHallwayFlag;
        private readonly EnabledRefRW<CellTypeIsRoom> cellTypeIsRoomFlag;
        private readonly EnabledRefRW<CellTypeIsSpace> cellTypeIsSpaceFlag;
        private readonly RefRW<CellTypeComponentData> cellTypeComponentData;

        public void SetCellTypeFlags(CellType cellType)
        {
            //Debug.Log(( cellType & CellType.Empty) != 0);
            cellTypeIsEmptyFlag.ValueRW = (cellType & CellType.Empty) != 0;
            cellTypeIsRoomFlag.ValueRW = (cellType & CellType.Room) != 0;
            CellTypeIsHallwayFlag.ValueRW = (cellType & CellType.Hallway) != 0;
            cellTypeIsSpaceFlag.ValueRW = (cellType & CellType.Space) != 0;
            cellTypeComponentData.ValueRW.value = cellType;
           
           
        }
    }
1 Like

One alternate approach is making CellTypeComponentData a shared component. Then if your CellType has 5 values, there will be 5 different chunks, each CellType value is the identity of a chunk. For that you can both have just 1 component and be able to query entities based on their CellType.
https://docs.unity3d.com/Packages/com.unity.entities@1.0/manual/components-shared-introducing.html

1 Like