I have come up with what I think is a neat pattern for using DynamicBuffers and am looking for some feedback before I get too carried away using it. Essentially it creates an easy and performant way to access individual values in a DynamicBuffer. Is there any performance concerns, or better ways to do something like this?
Here is a simple example of the pattern for a boolean state system.
The buffer data to be authored:
public enum StateType
{
None = -1,
Idle = 0,
InCombat = 1,
}
public struct StateData : IBufferElementData
{
public StateType Type;
public bool Active;
}
Abstract class to be used to author the different state types so they get added to the DynamicBuffer:
public abstract class StateAuthoring : MonoBehaviour, StateAuthoring.ICollect
{
public interface ICollect
{
StateData GetState(IBaker baker);
}
//override in authoring implementation to return a StateData with a StateType
public abstract StateData GetState(IBaker baker);
}
The buffer authoring class where the magic happens. It ensures that all enum values have a single entry in the DynamicBuffer. If there isn’t an associated authoring component for a state type it creates an empty placeholder to ensure enum indexes are always correct.
public class StatesAuthoring : MonoBehaviour
{
class Baker : Baker<StatesAuthoring>
{
public override void Bake(StatesAuthoring authoring)
{
Entity entity = GetEntity(TransformUsageFlags.Dynamic);
var statesBuffer = AddBuffer<StateData>(entity);
var components = GetComponents<StateAuthoring>();
var states = components.Select(c => c.GetState(this));
foreach (StateType stateType in System.Enum.GetValues(typeof(StateType)))
{
if (stateType == StateType.None) continue; // Skip None
try
{
var existingState = states.First(s => s.Type == stateType);
if (existingState.Type == stateType)
{
//Add the stat to the buffer
statesBuffer.Add(existingState);
}
else
{
//Add a placeholder for the missing stat with StatType.None
statesBuffer.Add(new StateData
{
Type = StateType.None,
active = false
});
}
}
catch (Exception e)
{
//Add a placeholder for the missing stat with StatType.None
statesBuffer.Add(new StateData
{
Type = StateType.None,
active = false
});
}
}
}
}
}
Simple usage example:
var combatState = stateBuffer[(int)StateType.InCombat];
//Is this a valid state in the buffer
if(combatState != StateType.None)
{
if(combatState.Active)
{
//Do something that depends on the state being active
}
}