Skip to content

Track value changes

Declare Reactive Component

public partial struct ExampleReactiveComponent : IReactiveValueChangeComponent
{
    private float3 _speed;
}
  • Must derive from IReactiveValueChangeComponent.
  • Must be partial definition.
  • Can be class or struct, can derive from IEnableableComponent.
  • All fields have to be private.
  • All fields names should be _camelCase with underscore prefix e.g. _speed.
  • Can not define any properties or methods.
  • Must have the corresponding Shadow Component defined.

This component definition will be automatically extended by:

  • Public properties setters, each one per each private field, these setters names are PascalCase e.g. Speed.
  • Public Publish() methods.

Declare Shadow Component

[TrackValueChange(typeof(ExampleReactiveComponent))]
public partial struct ExampleReactiveComponentHasChanged : IComponentData {}
  • Must be marked with TrackValueChange attribute which indicates the corresponding Reactive Component.
  • Must be partial struct.
  • Must derive from IComponentData.
  • Must be properly named with following rule: reactive component name + "HasChanged".
  • Must have the corresponding Reactive Component defined.

Make changes

Just set whatever field in Reactive Component you want (in whatever way you want e.g. by writing to ref argument in ForEach's delegate, via EntityManager or EntityCommandBuffer etc.).

After that you have to invoke Publish() on modified component instance.

EntityCommandBuffer.ParallelWriter commandBuffer = _commandBufferSystem.CreateCommandBuffer().AsParallelWriter();

Dependency = Entities
    .ForEach((Entity entity, int entityInQueryIndex, ref ExampleReactiveComponent component) => {
        component.Speed = ...;
        component.Publish(commandBuffer, entityInQueryIndex, entity);
    })
    .ScheduleParallel(Dependency);

_commandBufferSystem.AddJobHandleForProducer(Dependency);

In the case that the component value is created on the stack Publish has to be called before the component data is sent to ECS. Otherwise validation will complain about changes that were not published.

EntityCommandBuffer commandBuffer = _commandBufferSystem.CreateCommandBuffer();

ExampleReactiveComponent component = new ExampleReactiveComponent { Speed = ... };
component.Publish(commandBuffer, entity);
EntityManager.SetComponentData(entity,component);

Listen for changes

Entities
    .WithAll<ExampleReactiveComponentHasChanged>()
    .ForEach((Entity entity, ExampleReactiveComponent component) => { ... })
    .Run();