### Root Documentation Files Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/MANIFEST.md Lists the main documentation files located in the root directory, including the index, overview, examples, and configuration guides. ```text output/ ├── INDEX.md (Navigation hub, 11KB) ├── README.md (Overview, 11KB) ├── examples.md (7 working examples, 17KB) ├── types.md (Type definitions, 6.6KB) ├── configuration.md (Setup & tuning, 8.5KB) ├── errors.md (Exception catalog, 12KB) └── MANIFEST.md (This file) ``` -------------------------------- ### Install Entities Events via Git URL Source: https://github.com/annulusgames/entitiesevents/blob/main/README.md Install the Entities Events package by adding its Git URL to the Unity Package Manager. ```bash https://github.com/AnnulusGames/EntitiesEvents.git?path=Assets/EntitiesEvents ``` -------------------------------- ### Full Example: Event Definition and System Usage Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/RegisterEventAttribute.md A comprehensive example showing the definition of event types, their registration using RegisterEventAttribute, and their subsequent usage within ECS systems via EventWriter and EventReader. ```csharp // Events.cs - Define your event types using EntitiesEvents; public struct PlayerDamagedEvent { public int damage; public int3 hitPosition; } public struct PlayerHealedEvent { public int healAmount; } [assembly: RegisterEvent(typeof(PlayerDamagedEvent))] [assembly: RegisterEvent(typeof(PlayerHealedEvent))] // Systems.cs - Use the events using Unity.Burst; using Unity.Entities; using EntitiesEvents; [BurstCompile] public partial struct DamageSystem : ISystem { EventWriter damageWriter; [BurstCompile] public void OnCreate(ref SystemState state) { damageWriter = state.GetEventWriter(); } [BurstCompile] public void OnUpdate(ref SystemState state) { damageWriter.Write(new PlayerDamagedEvent { damage = 10, hitPosition = new int3(0, 1, 0) }); } } [BurstCompile] public partial struct HealthSystem : ISystem { EventReader damageReader; [BurstCompile] public void OnCreate(ref SystemState state) { damageReader = state.GetEventReader(); } [BurstCompile] public void OnUpdate(ref SystemState state) { foreach (var evt in damageReader.Read()) { // Reduce health by evt.damage } } } ``` -------------------------------- ### UnsafeEvents Constructor Example Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/UnsafeEvents.md Demonstrates how to instantiate UnsafeEvents, get a writer, write an event, and dispose of the buffer. Ensure proper disposal using a try-finally block. ```csharp var unsafeEvents = new UnsafeEvents(1024, Allocator.Persistent); try { var writer = unsafeEvents.GetWriter(); writer.Write(new MyEvent()); } finally { unsafeEvents.Dispose(); } ``` -------------------------------- ### Basic Event Flow Example Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/README.md Demonstrates the fundamental pattern for defining, registering, writing, and reading events using EventWriter and EventReader. Ensure event types are unmanaged. ```csharp // 1. Define event type (must be unmanaged) public struct PlayerDamagedEvent { public int damage; } // 2. Register for code generation [assembly: RegisterEvent(typeof(PlayerDamagedEvent))] // 3. Write system [BurstCompile] public partial struct DamageSystem : ISystem { EventWriter writer; [BurstCompile] public void OnCreate(ref SystemState state) { writer = state.GetEventWriter(); } [BurstCompile] public void OnUpdate(ref SystemState state) { writer.Write(new PlayerDamagedEvent { damage = 10 }); } } // 4. Read system [BurstCompile] public partial struct HealthSystem : ISystem { EventReader reader; [BurstCompile] public void OnCreate(ref SystemState state) { reader = state.GetEventReader(); } [BurstCompile] public void OnUpdate(ref SystemState state) { foreach (var evt in reader.Read()) { // Reduce health by evt.damage } } } ``` -------------------------------- ### Custom Event System Implementation Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/EventSystemBase.md Example of implementing a custom event system by inheriting from EventSystemBase and using EventReader to process events. ```csharp public struct PlayerDeathEvent { public Entity player; public Vector3 deathPosition; } [UpdateInGroup(typeof(EventSystemGroup))] public partial class PlayerDeathSystem : EventSystemBase { private EventReader reader; protected override void OnCreate() { base.OnCreate(); reader = GetEventReader(); } protected override void OnUpdate() { base.OnUpdate(); // Call base to update buffers int deathCount = 0; foreach (var evt in reader.Read()) { deathCount++; Debug.Log($"Player at {evt.deathPosition} died"); } if (deathCount > 0) { Debug.Log($"Total deaths this frame: {deathCount}"); } } } ``` -------------------------------- ### Create Events Container with Initial Capacity Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/Events.md Initializes a new `Events` container with a specified initial capacity and memory allocator. This example demonstrates creating, writing, reading, and then disposing of the container. ```csharp // Create an event container with 512-element initial capacity var events = new Events(512, Allocator.Persistent); try { var writer = events.GetWriter(); var reader = events.GetReader(); // Write and read events writer.Write(new MyEvent { id = 1 }); foreach (var evt in reader.Read()) { Debug.Log($"Event received: {evt.id}"); } } finally { events.Dispose(); } ``` -------------------------------- ### Install Entities Events via manifest.json Source: https://github.com/annulusgames/entitiesevents/blob/main/README.md Add the Entities Events package to your project's manifest.json file. ```json { "dependencies": { "com.annulusgames.entities-events": "https://github.com/AnnulusGames/EntitiesEvents.git?path=Assets/EntitiesEvents" } } ``` -------------------------------- ### Create a new Events container Source: https://github.com/annulusgames/entitiesevents/blob/main/README.md Instantiates a new Events container with a specified capacity and memory allocator. This is the initial setup for storing events. ```cs using Unity.Collections; using EntitiesEvents; // Create a new Events var events = new Events(32, Allocator.Temp); ``` -------------------------------- ### Custom Event System Implementation Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/EventSystemBase.md An advanced example of a completely custom event system using Events for maximum control. This implementation does not inherit from EventSystemBase. ```csharp [UpdateInGroup(typeof(EventSystemGroup))] [BurstCompile] public partial struct CustomEventSystem : ISystem { private Events events; private EventWriter writer; private EventReader reader; [BurstCompile] public void OnCreate(ref SystemState state) { events = new Events(512, Allocator.Persistent); writer = events.GetWriter(); reader = events.GetReader(); } [BurstCompile] public void OnUpdate(ref SystemState state) { // Process events foreach (var evt in reader.Read()) { // Handle event } // Update buffers events.Update(); } [BurstCompile] public void OnDestroy() { events.Dispose(); } } ``` -------------------------------- ### Unmanaged Type Constraint Examples Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/types.md Demonstrates valid and invalid types for the 'unmanaged' constraint. Unmanaged types ensure no GC overhead and Burst compatibility. ```csharp // Valid: unmanaged value types struct MyEvent { public int id; public float3 pos; } // ✓ struct SimpleEvent { } // ✓ int // ✓ // Invalid: managed types string name; // ✗ reference type int[] items; // ✗ array class MyClass { } // ✗ reference type ``` -------------------------------- ### Buffer Overflow Prevention with EnsureBufferCapacity Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/errors.md Demonstrates how to prevent buffer overflows when using WriteNoResize by ensuring sufficient capacity is pre-allocated. This example shows both the incorrect approach (no pre-allocation) and the correct approach using EnsureBufferCapacity. ```csharp var events = new Events(10, Allocator.Persistent); // ✗ No pre-allocation - assuming 512 events will fit in capacity of 10 state.EnsureBufferCapacity(512); var writer = state.GetEventWriter(); for (int i = 0; i < 512; i++) { // Safe after EnsureBufferCapacity writer.WriteNoResize(new MyEvent()); } // ✗ Without EnsureBufferCapacity - will overflow in release build for (int i = 0; i < 100; i++) { writer.WriteNoResize(new MyEvent()); // Undefined behavior if i >= 10 } ``` -------------------------------- ### Get UnsafeEventWriter Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/UnsafeEvents.md Demonstrates obtaining an UnsafeEventWriter to write events to the buffer. This bypasses safety checks for performance. ```csharp var writer = unsafeEvents.GetWriter(); writer.Write(new MyEvent { id = 1 }); ``` -------------------------------- ### Get UnsafeEventReader Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/UnsafeEvents.md Shows how to obtain an UnsafeEventReader to iterate over and process events from the buffer. Use this when direct memory access is needed. ```csharp var reader = unsafeEvents.GetReader(); foreach (var evt in reader.Read()) { // Process event } ``` -------------------------------- ### GetEventWriter for SystemBase Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/EventHelper.md Use this method in class-based systems to get an EventWriter. It's suitable for systems derived from SystemBase. ```csharp public static EventWriter GetEventWriter(this SystemBase systemBase) where T : unmanaged ``` ```csharp public partial class WriteEventSystemClass : SystemBase { EventWriter eventWriter; protected override void OnCreate() { // Works in class-based systems eventWriter = this.GetEventWriter(); } protected override void OnUpdate() { eventWriter.Write(new MyEvent { id = 1 }); } } ``` -------------------------------- ### Events.IsCreated Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/Events.md Gets whether the Events container has been successfully allocated. This property indicates if the container is ready for use. ```APIDOC ## IsCreated ### Description Gets whether the Events container has been successfully allocated. ### Method Property Accessor ### Parameters - None ### Example ```csharp var events = new Events(512, Allocator.Persistent); if (events.IsCreated) { var writer = events.GetWriter(); writer.Write(new MyEvent()); } ``` ``` -------------------------------- ### Dispose UnsafeEvents Buffer Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/UnsafeEvents.md Provides an example of correctly disposing of the UnsafeEvents buffer to free allocated memory. This is crucial for preventing memory leaks. ```csharp var unsafeEvents = new UnsafeEvents(512, Allocator.Persistent); try { // Use the events } finally { unsafeEvents.Dispose(); } ``` -------------------------------- ### Iterate Over New Events with UnsafeEventReader Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/UnsafeEventReader.md Shows how to use UnsafeEventReader.Read() to get an iterator for unread events. Subsequent calls to Read() on the same reader will yield only newly written events. ```csharp var reader = unsafeEvents.GetReader(); foreach (var evt in reader.Read()) { // Process each event once } // Calling Read() again yields only new events since last call foreach (var evt in reader.Read()) { // Process new events } ``` -------------------------------- ### Invalid Event Type Examples Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/RegisterEventAttribute.md Demonstrates C# struct definitions that are not suitable for event types due to containing reference types (string, array) or unsupported types like Entity. These will cause compilation errors. ```csharp public struct BadEvent1 { public string name; // Reference type - INVALID } public struct BadEvent2 { public Entity entity; // Not supported in event types } public struct BadEvent3 { public int[] items; // Array - INVALID } ``` -------------------------------- ### Best Practice: Handle Dependencies Correctly Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/EventSystemBase.md Allow the base class to manage system dependencies by calling base.OnCreate(). Do not manually modify the RequireForUpdate requirement after this call. ```csharp protected override void OnCreate() { base.OnCreate(); // Sets up RequireForUpdate // Don't modify the requirement } ``` -------------------------------- ### IsCreated Property Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/UnsafeEvents.md Gets a boolean value indicating whether the event buffer has been successfully allocated. ```APIDOC ## IsCreated Property ### Description Gets whether the buffer has been successfully allocated. ### Signature ```csharp public bool IsCreated { get; } ``` ### Type bool ### Example ```csharp if (unsafeEvents.IsCreated) { var reader = unsafeEvents.GetReader(); } ``` ``` -------------------------------- ### Typical Event Writing with EventHelper Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/UnsafeEventWriter.md Demonstrates the standard and recommended way to write events using the safe EventWriter accessed via EventHelper. This approach includes safety checks for general use. ```csharp var writer = state.GetEventWriter(); writer.Write(new MyEvent()); ``` -------------------------------- ### Event System Execution Order Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/configuration.md Illustrates the default execution order of event systems within the SimulationSystemGroup and how to control custom system order using UpdateBefore and UpdateAfter attributes. ```csharp SimulationSystemGroup (OrderLast = true) └── EventSystemGroup ├── Generated EventSystem ├── Generated EventSystem └── User systems (optional) ``` ```csharp // Run before generated event systems update buffers [UpdateInGroup(typeof(EventSystemGroup))] [UpdateBefore(typeof(EventSystemGroup))] public partial struct PreUpdateSystem : ISystem { } // Run after event systems update buffers [UpdateInGroup(typeof(EventSystemGroup))] [UpdateAfter(typeof(EventSystemGroup))] public partial struct PostUpdateSystem : ISystem { } ``` -------------------------------- ### Default Event Container Creation via EventHelper Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/configuration.md Use EventHelper extension methods to automatically create event containers with default settings. Pre-allocate capacity if a different size is needed. ```csharp var writer = state.GetEventWriter(); // Internally creates: // new Events(512, Allocator.Persistent) state.EnsureBufferCapacity(2048); ``` -------------------------------- ### OnCreate() Implementation Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/EventSystemBase.md Ensures the system only runs when an EventSingleton exists, which is created on first event writer/reader access. ```csharp [BurstCompile] protected override void OnCreate() { RequireForUpdate>(); } ``` -------------------------------- ### EventsDataIterator Structure Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/types.md Iterates over unread events in the event buffers, starting from a specified sequence number. Implements IEnumerable for foreach compatibility. ```csharp public readonly unsafe ref struct EventsDataIterator where T : unmanaged { public EventsDataIterator(EventsData* buffer, uint eventCounter); public Enumerator GetEnumerator(); public struct Enumerator : IEnumerator { public T Current { get; } object IEnumerator.Current { get; } public bool MoveNext(); public void Reset(); public void Dispose(); } } ``` ```csharp var reader = events.GetReader(); EventsDataIterator iter = reader.Read(); foreach (var evt in iter) { // evt is MyEvent // Only events >= internal counter are yielded } ``` -------------------------------- ### Create and Read Events with EventReader Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/EventReader.md Demonstrates how to create an EventReader and iterate over its events. Ensure you have a defined event struct like MyEvent. ```csharp var events = new Events(512, Allocator.Persistent); var reader = new EventReader(in events); foreach (var evt in reader.Read()) { Debug.Log("Received event!"); } ``` -------------------------------- ### Parallel Event Writing with IJobEntity Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/README.md Illustrates how to write events in parallel from multiple entities using IJobEntity. Ensure buffer capacity is pre-allocated before scheduling the job. ```csharp [BurstCompile] public partial struct ParallelWriteSystem : ISystem { [BurstCompile] public void OnUpdate(ref SystemState state) { // Pre-allocate before parallel write state.EnsureBufferCapacity(4096); var writer = state.GetEventWriter(); var job = new WriteEventJob { writer = writer }; job.ScheduleParallel().Complete(); } } [BurstCompile] public struct WriteEventJob : IJobEntity { public EventWriter writer; [BurstCompile] void Execute() { writer.WriteNoResize(new MyEvent()); } } ``` -------------------------------- ### System Execution Order for Event Readers and Writers Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/errors.md Explains the impact of system execution order on event delivery. It shows how a reader running before a writer introduces a one-frame delay and provides the solution to avoid this delay. ```csharp // Frame N [UpdateBefore(typeof(WriteEventSystem))] public partial struct ReadEventSystem : ISystem { } // Reads frame N-1 events public partial struct WriteEventSystem : ISystem { } // Writes frame N events // Frame N+1 // ReadEventSystem will receive frame N events // This is expected behavior, not an error ``` ```csharp [UpdateBefore(typeof(ReadEventSystem))] public partial struct WriteEventSystem : ISystem { } public partial struct ReadEventSystem : ISystem { } ``` -------------------------------- ### Typical EventReader Usage (Safe Version) Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/UnsafeEventReader.md Illustrates the common pattern for using the safe EventReader via EventHelper. This is the recommended approach for general use. ```csharp var reader = state.GetEventReader(); foreach (var evt in reader.Read()) { // Process event } ``` -------------------------------- ### Best Practice: Cache Readers and Writers Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/EventSystemBase.md Obtain event readers and writers once during the OnCreate phase for efficiency. This avoids repeated allocations and lookups during system updates. ```csharp EventReader reader; protected override void OnCreate() { base.OnCreate(); reader = GetEventReader(); } ``` -------------------------------- ### Using Unsafe Event Writers Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/configuration.md Shows how to switch from the safe EventWriter to the UnsafeEventWriter for performance-critical paths after profiling indicates safety checks are a bottleneck. Requires an unsafe context. ```csharp // Development: Use safe version var writer = state.GetEventWriter(); // After profiling, if safety checks are a bottleneck: // Switch to UnsafeEventWriter (requires unsafe context) ``` -------------------------------- ### Specialized UnsafeEventReader Usage Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/UnsafeEventReader.md Provides an example of using UnsafeEventReader within a custom event queue implementation. This is suitable for scenarios requiring direct control over event handling. ```csharp public class CustomEventQueue { readonly UnsafeEvents events; public IEnumerable GetPendingEvents() { var reader = events.GetReader(); return reader.Read(); } } ``` -------------------------------- ### Manual Event Management with Events Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/README.md Shows how to manually manage the event lifecycle using the Events container, including explicit buffer swapping and disposal. Use this for full control over event management. ```csharp var events = new Events(512, Allocator.Persistent); try { var writer = events.GetWriter(); writer.Write(new MyEvent()); events.Update(); // Swap buffers manually var reader = events.GetReader(); foreach (var evt in reader.Read()) { // Process } } finally { events.Dispose(); } ``` -------------------------------- ### Get EventReader using EntityManager Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/EventHelper.md Obtains or creates an EventReader for a specific event type using direct EntityManager access. Use this when you need to read events directly from the entity manager. ```csharp public static EventReader GetEventReader(this EntityManager entityManager) where T : unmanaged ``` ```csharp var reader = world.EntityManager.GetEventReader(); foreach (var evt in reader.Read()) { // Process event } ``` -------------------------------- ### Valid Event Type Examples Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/RegisterEventAttribute.md Illustrates valid C# struct definitions for event types that can be registered with RegisterEventAttribute. These types must be unmanaged, contain no reference types, and consist of blittable or native fields. ```csharp public struct SimpleEvent { } public struct EventWithData { public int id; public float3 position; public uint flags; } public struct EventWithEnum { public PlayerAction action; // Enum is OK } public enum PlayerAction { Jump, Attack, Defend } ``` -------------------------------- ### Basic Event Registration Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/RegisterEventAttribute.md Demonstrates how to register a single event type at the assembly level using the RegisterEventAttribute. Ensure the attribute is placed in a .cs file within your assembly. ```csharp using EntitiesEvents; public struct MyEvent { public int id; public float value; } [assembly: RegisterEvent(typeof(MyEvent))] ``` -------------------------------- ### Multiple Event Registrations Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/RegisterEventAttribute.md Shows how to register multiple event types by applying the RegisterEventAttribute multiple times within the same assembly. ```csharp [assembly: RegisterEvent(typeof(PlayerMovedEvent))] [assembly: RegisterEvent(typeof(PlayerDamagedEvent))] [assembly: RegisterEvent(typeof(PlayerDiedEvent))] ``` -------------------------------- ### Custom System Integration - Pre-Event Processing Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/EventSystemGroup.md A custom system that runs before the event buffer updates within the EventSystemGroup. Useful for pre-event processing logic. ```csharp using Unity.Entities; [UpdateInGroup(typeof(EventSystemGroup))] [UpdateBefore(typeof(EventSystemGroup))] // Run before event buffer updates public partial struct PreEventProcessingSystem : ISystem { public void OnUpdate(ref SystemState state) { // Executes before EventSystemGroup's OnUpdate } } ``` -------------------------------- ### Capacity Sizing Strategy: Conservative Default Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/configuration.md Use a default capacity between 512 and 1024 for typical game systems when pre-allocating buffer capacity. ```csharp state.EnsureBufferCapacity(1024); ``` -------------------------------- ### Control System Execution Order Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/README.md Specifies that a writer system should execute before a reader system using the UpdateBefore attribute. This helps manage dependencies and ensures data is available when needed. ```csharp [UpdateBefore(typeof(ReaderSystem))] public partial struct WriterSystem : ISystem { } ``` -------------------------------- ### Optimize Event Buffer Resizing Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/configuration.md Compares inefficient buffer writing that may trigger frequent resizes with a more performant approach that pre-allocates buffer capacity. ```csharp // Avoid: Buffer resizes every frame var writer = state.GetEventWriter(); for (int i = 0; i < 10000; i++) { writer.Write(new MyEvent()); // May trigger multiple resizes } // Better: Pre-allocate state.EnsureBufferCapacity(10000); var writer = state.GetEventWriter(); for (int i = 0; i < 10000; i++) { writer.Write(new MyEvent()); // No resizes } ``` -------------------------------- ### Synchronization with Automatic Systems Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/EventSystemBase.md Demonstrates how a custom EventSystemBase can read events shared with automatically generated event systems. Ensure the event type is registered using [assembly: RegisterEvent]. ```csharp public struct SharedEvent { public int value; } [assembly: RegisterEvent(typeof(SharedEvent))] [UpdateInGroup(typeof(EventSystemGroup))] public partial class CustomEventSystem : EventSystemBase { EventReader reader; protected override void OnCreate() { base.OnCreate(); reader = GetEventReader(); } protected override void OnUpdate() { base.OnUpdate(); // Reads events written by: // 1. Other systems using GetEventWriter() // 2. The generated EventSystem foreach (var evt in reader.Read()) { // Process shared event } } } ``` -------------------------------- ### Best Practice: Call base.OnUpdate() Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/EventSystemBase.md Ensures that buffer updates are correctly handled by calling the base class's OnUpdate method. This should be the first line in your OnUpdate implementation. ```csharp protected override void OnUpdate() { base.OnUpdate(); // Your logic here } ``` -------------------------------- ### Simple One-Way Event: Player Fire Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/examples.md Demonstrates a player input system writing a 'WeaponFiredEvent' and a projectile spawner system reading and reacting to it. Ensure the 'WeaponFiredEvent' struct and the 'RegisterEvent' attribute are defined. ```csharp // Define the event public struct WeaponFiredEvent { public Entity firedBy; public float3 position; public float3 direction; } [assembly: RegisterEvent(typeof(WeaponFiredEvent))] // Writer system: handles player input [BurstCompile] public partial struct PlayerInputSystem : ISystem { EventWriter fireWriter; [BurstCompile] public void OnCreate(ref SystemState state) { fireWriter = state.GetEventWriter(); } [BurstCompile] public void OnUpdate(ref SystemState state) { foreach (var (playerInput, transform) in SystemAPI.Query()) { if (playerInput.FireButton) { fireWriter.Write(new WeaponFiredEvent { firedBy = SystemAPI.GetEntity(playerInput), position = transform.Position, direction = math.forward(transform.Value.rot) }); } } } } // Reader system: spawns projectiles [BurstCompile] public partial struct ProjectileSpawnerSystem : ISystem { EventReader fireReader; EntityCommandBuffer.ParallelWriter ecb; [BurstCompile] public void OnCreate(ref SystemState state) { fireReader = state.GetEventReader(); } [BurstCompile] public void OnUpdate(ref SystemState state) { var ecbSingleton = SystemAPI.GetSingleton(); ecb = ecbSingleton.CreateCommandBuffer(state.WorldUnmanaged).AsParallelWriter(); int eventIndex = 0; foreach (var evt in fireReader.Read()) { var projectile = state.EntityManager.Instantiate(SystemAPI.GetSingleton().projectile); state.EntityManager.SetComponentData(projectile, new LocalToWorld { Value = float4x4.TRS(evt.position, quaternion.identity, float3.one) }); state.EntityManager.SetComponentData(projectile, new Velocity { Value = evt.direction * 20f }); eventIndex++; } } } ``` -------------------------------- ### Custom Event System with Manual Buffer Control Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/examples.md Create a custom event system that allows processing events multiple times per frame, both before and after buffer updates. This provides fine-grained control over event consumption. ```csharp public struct CustomMessageEvent { public uint messageId; public float3 data; } [assembly: RegisterEvent(typeof(CustomMessageEvent))] // Custom system with manual buffer control [UpdateInGroup(typeof(EventSystemGroup))] [BurstCompile] public partial struct CustomEventProcessingSystem : EventSystemBase { EventReader reader; [BurstCompile] protected override void OnCreate() { base.OnCreate(); reader = GetEventReader(); } [BurstCompile] protected override void OnUpdate() { // Process events BEFORE buffer update ProcessEvents(); // Update buffers (from base class) base.OnUpdate(); // Process new events AFTER buffer update ProcessEvents(); } void ProcessEvents() { int count = 0; foreach (var evt in reader.Read()) { // Process each event count++; } if (count > 0) { Debug.Log($ ``` -------------------------------- ### Custom System Integration - Post-Event Processing Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/EventSystemGroup.md A custom system that runs after the event buffer updates within the EventSystemGroup. Useful for post-event processing logic. ```csharp using Unity.Entities; [UpdateInGroup(typeof(EventSystemGroup))] [UpdateAfter(typeof(EventSystemGroup))] // Run after event buffer updates public partial struct PostEventProcessingSystem : ISystem { public void OnUpdate(ref SystemState state) { // Executes after EventSystemGroup's OnUpdate // New buffers are ready for writing } } ``` -------------------------------- ### Write Events using EventWriter in ISystem Source: https://github.com/annulusgames/entitiesevents/blob/main/README.md In a sending System inheriting from ISystem, obtain an EventWriter in OnCreate and use its Write method to publish events. ```csharp using Unity.Burst; using Unity.Entities; using EntitiesEvents; [BurstCompile] public partial struct WriteEventSystem : ISystem { // Cache the obtained EventWriter within the System EventWriter eventWriter; [BurstCompile] public void OnCreate(ref SystemState state) { // Obtain the EventWriter with GetEventWriter eventWriter = state.GetEventWriter(); } [BurstCompile] public void OnUpdate(ref SystemState state) { // Publish the event using Write eventWriter.Write(new MyEvent()); } } ``` -------------------------------- ### Write Events using EventWriter in SystemBase Source: https://github.com/annulusgames/entitiesevents/blob/main/README.md For Systems inheriting from SystemBase, use 'this.GetEventWriter()' in OnCreate to obtain the EventWriter. ```csharp using Unity.Burst; using Unity.Entities; using EntitiesEvents; [BurstCompile] public partial class WriteEventSystemClass : SystemBase { EventWriter eventWriter; [BurstCompile] protected override OnCreate() { // Obtain the EventWriter with this.GetEventWriter eventWriter = this.GetEventWriter(); } [BurstCompile] protected override void OnUpdate() { eventWriter.Write(new MyEvent()); } } ``` -------------------------------- ### Manual Event Buffer Control Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/EventSystemGroup.md Demonstrates manual control over event buffers using Events for custom update timing, bypassing the automatic EventSystemGroup management. ```csharp using Unity.Entities; public partial struct CustomEventSystem : ISystem { Events events; public void OnCreate(ref SystemState state) { events = new Events(512, Allocator.Persistent); } public void OnUpdate(ref SystemState state) { // Manual read var reader = events.GetReader(); foreach (var evt in reader.Read()) { } // Manual write var writer = events.GetWriter(); writer.Write(new MyEvent()); // Manual buffer update (instead of automatic) events.Update(); } public void OnDestroy() { events.Dispose(); } } ``` -------------------------------- ### Event Instance Construction Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/types.md Illustrates how an EventInstance is created and added to a buffer when EventWriter.Write is called. The eventCounter is incremented for the next event. ```csharp var instance = new EventInstance(value, buffer->eventCounter); buffer->eventCounter++; // Increment for next event // Add instance to appropriate buffer ``` -------------------------------- ### Manual Event Container Lifecycle Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/configuration.md Demonstrates manual creation, usage, and explicit disposal of an Events container. Failing to dispose manual containers will result in memory leaks. ```csharp // Create var events = new Events(512, Allocator.Persistent); // Use var writer = events.GetWriter(); writer.Write(new MyEvent()); // Must dispose explicitly events.Dispose(); // Release memory // After dispose, IsCreated returns false if (!events.IsCreated) { // Cannot use events } ``` -------------------------------- ### OnUpdate() Implementation Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/EventSystemBase.md Calls Events.Update() on the singleton's event container to perform buffer swap and state updates. This runs in EventSystemGroup after other simulation systems. ```csharp [BurstCompile] protected override void OnUpdate() { CompleteDependency(); SystemAPI.GetSingleton>().events.Update(); } ``` -------------------------------- ### Manual Event Container Creation Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/configuration.md Create Events containers directly, specifying the initial capacity and allocator. This provides fine-grained control over memory management. ```csharp var tempEvents = new Events(16, Allocator.Temp); // Medium persistent container var events = new Events(512, Allocator.Persistent); // Large pre-allocated container var largeEvents = new Events(4096, Allocator.Persistent); ``` -------------------------------- ### Release Build Behavior Without Safety Checks Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/errors.md Illustrates that release builds skip safety checks, potentially leading to undefined behavior if not handled carefully. It shows the importance of manual checks when safety features are disabled. ```csharp // Release builds skip safety checks events.Dispose(); var writer = events.GetWriter(); // No exception in release! // But behavior is undefined // Always check manually: if (events.IsCreated) { var writer = events.GetWriter(); } ``` -------------------------------- ### Two-Way Resource Request and Grant Events Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/examples.md Defines the event structures for resource requests and grants, along with the systems that handle sending and processing these events. This pattern is useful for decoupled communication between game systems. ```csharp // Request event public struct ResourceRequestEvent { public Entity requester; public int resourceId; public int amount; } // Response event public struct ResourceGrantedEvent { public Entity requester; public int amount; public bool success; } [assembly: RegisterEvent(typeof(ResourceRequestEvent))] [assembly: RegisterEvent(typeof(ResourceGrantedEvent))] // Requester system [BurstCompile] public partial struct ResourceRequesterSystem : ISystem { EventWriter requestWriter; EventReader responseReader; [BurstCompile] public void OnCreate(ref SystemState state) { requestWriter = state.GetEventWriter(); responseReader = state.GetEventReader(); } [BurstCompile] public void OnUpdate(ref SystemState state) { // Process responses from previous frame foreach (var response in responseReader.Read()) { if (response.success) { Debug.Log($"Received {response.amount} resources"); } } // Send new request requestWriter.Write(new ResourceRequestEvent { requester = SystemAPI.GetEntity(SystemAPI.GetSingletonEntity()), resourceId = 1, amount = 10 }); } } // Resource manager system [BurstCompile] public partial struct ResourceManagerSystem : ISystem { EventReader requestReader; EventWriter responseWriter; ResourcePool resourcePool; [BurstCompile] public void OnCreate(ref SystemState state) { requestReader = state.GetEventReader(); responseWriter = state.GetEventWriter(); resourcePool = new ResourcePool { gold = 1000 }; } [BurstCompile] public void OnUpdate(ref SystemState state) { foreach (var request in requestReader.Read()) { bool success = false; int granted = 0; if (resourcePool.gold >= request.amount) { resourcePool.gold -= request.amount; granted = request.amount; success = true; } responseWriter.Write(new ResourceGrantedEvent { requester = request.requester, amount = granted, success = success }); } } } public struct ResourcePool : IComponentData { public int gold; } ``` -------------------------------- ### Singleton Event Container Lifecycle Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/configuration.md Explains that singletons created via EventHelper have a lifetime tied to the world and are automatically managed. Manual cleanup is an advanced option. ```csharp // Created automatically on first access var writer = state.GetEventWriter(); // Destroyed when: // - World is destroyed // - EventSystem for this type explicitly destroys it // - Manual cleanup (advanced usage) ``` -------------------------------- ### Create and Read UnsafeEventReader Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/UnsafeEventReader.md Demonstrates how to create an UnsafeEventReader from an UnsafeEvents container and iterate over its events. Ensure UnsafeEvents and MyEvent are defined. ```csharp var unsafeEvents = new UnsafeEvents(512, Allocator.Persistent); var reader = new UnsafeEventReader(in unsafeEvents); foreach (var evt in reader.Read()) { Debug.Log($ ``` -------------------------------- ### Capacity Sizing Strategy: Peak Frame Load Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/configuration.md Estimate the maximum number of events expected per frame and multiply by 1.5 for a safety margin when pre-allocating capacity. ```csharp // If max 1000 events per frame state.EnsureBufferCapacity(1500); ``` -------------------------------- ### Control Event System Execution Order Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/RegisterEventAttribute.md Use UpdateBefore and UpdateAfter attributes to define the execution order between event systems. This ensures that one system completes its logic before another begins, which is crucial for dependent event processing. ```csharp [UpdateBefore(typeof(HealthSystem))] public partial struct DamageSystem : ISystem { } [UpdateAfter(typeof(DamageSystem))] public partial struct HealthSystem : ISystem { } ``` -------------------------------- ### Conditional Safety Checks with ENABLE_UNITY_COLLECTIONS_CHECKS Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/errors.md This code demonstrates how to conditionally execute safety checks based on the ENABLE_UNITY_COLLECTIONS_CHECKS preprocessor directive. It is useful for enabling detailed checks in development builds while optimizing release builds. ```csharp #if ENABLE_UNITY_COLLECTIONS_CHECKS // This code runs in Editor and Development builds AtomicSafetyHandle.CheckWriteAndThrow(m_Safety); #endif ``` -------------------------------- ### API Reference Directory Structure Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/MANIFEST.md Details the files organized within the 'api-reference' directory, each covering specific components of the Entities Events API. ```text api-reference/ ├── EventWriter.md (3.6KB) ├── EventReader.md (3.3KB) ├── Events.md (5.0KB) ├── EventHelper.md (8.9KB) ├── RegisterEventAttribute.md (5.8KB) ├── EventSystemGroup.md (5.2KB) ├── EventSystemBase.md (7.1KB) ├── UnsafeEvents.md (4.6KB) ├── UnsafeEventWriter.md (3.9KB) └── UnsafeEventReader.md (3.8KB) ``` -------------------------------- ### Publish an Event Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/README.md Obtains an event writer for a specific event type and writes a new event instance. Ensure the event type is registered before writing. ```csharp var writer = state.GetEventWriter(); writer.Write(new MyEvent { /* ... */ }); ``` -------------------------------- ### Capacity Sizing Strategy: Large-Scale Systems Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/configuration.md Use a large capacity, such as 65536, for systems that handle high-frequency messaging. ```csharp state.EnsureBufferCapacity(65536); ``` -------------------------------- ### Correct Event Reading with Consistent Read() Calls Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/errors.md Presents the correct approach to reading events by always calling `reader.Read()` every frame, even if no events are expected. This ensures the reader state is updated and prevents event loss. ```csharp [BurstCompile] public partial struct GoodReaderSystem : ISystem { EventReader reader; [BurstCompile] public void OnCreate(ref SystemState state) { reader = state.GetEventReader(); } [BurstCompile] public void OnUpdate(ref SystemState state) { // Always call Read() every frame, even if empty int count = 0; foreach (var evt in reader.Read()) { count++; } // count may be 0, but reader state is updated } } ``` -------------------------------- ### Read Events using EventReader in ISystem Source: https://github.com/annulusgames/entitiesevents/blob/main/README.md In a receiving System inheriting from ISystem, obtain an EventReader in OnCreate and iterate through eventReader.Read() to process events. ```csharp using Unity.Burst; using Unity.Entities; using EntitiesEvents; [BurstCompile] public partial struct ReadEventSystem : ISystem { // Cache the obtained EventReader within the System EventReader eventReader; [BurstCompile] public void OnCreate(ref SystemState state) { // Obtain the EventReader with GetEventReader eventReader = state.GetEventReader(); } [BurstCompile] public void OnUpdate(ref SystemState state) { // Read unread events with eventReader.Read() foreach (var eventData in eventReader.Read()) { Debug.Log("received!"); } } } ``` -------------------------------- ### Events Constructor Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/Events.md Creates a new Events container with dual-buffering for frame-based event management. It requires an initial capacity for each buffer and a memory allocator. ```APIDOC ## Events(int initialCapacity, Allocator allocator) ### Description Creates a new Events container with dual-buffering for frame-based event management. ### Method Constructor ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - None ### Parameters - **initialCapacity** (int) - Required - Initial capacity for each buffer (must be >= 0) - **allocator** (Allocator) - Required - Memory allocator (Temp, TempJob, or Persistent) ### Example ```csharp // Create an event container with 512-element initial capacity var events = new Events(512, Allocator.Persistent); try { var writer = events.GetWriter(); var reader = events.GetReader(); // Write and read events writer.Write(new MyEvent { id = 1 }); foreach (var evt in reader.Read()) { Debug.Log($"Event received: {evt.id}"); } } finally { events.Dispose(); } ``` ``` -------------------------------- ### Manual Enumeration with EventsDataIterator Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/UnsafeEventReader.md Demonstrates manual enumeration of events using the EventsDataIterator returned by UnsafeEventReader.Read(). This provides the same results as a standard foreach loop. ```csharp var reader = unsafeEvents.GetReader(); // Standard foreach foreach (var evt in reader.Read()) { // evt is of type T } // Manual enumeration var iter = reader.Read(); foreach (var evt in iter) { // Same result } ``` -------------------------------- ### Ensure Buffer Capacity with EntityManager Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/EventHelper.md Pre-allocates buffer capacity for an event type using the EntityManager. This is useful for optimizing performance by avoiding dynamic buffer resizing. ```csharp public static unsafe void EnsureBufferCapacity(EntityManager entityManager, int capacity) where T : unmanaged ``` ```csharp var manager = world.EntityManager; manager.EnsureBufferCapacity(1024); ``` -------------------------------- ### Pre-allocate Capacity for Parallel Writes Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/configuration.md Pre-allocate buffer capacity using EnsureBufferCapacity before scheduling parallel jobs that use WriteNoResize. This prevents runtime errors as WriteNoResize assumes sufficient capacity. ```csharp [BurstCompile] public partial struct ParallelEventSystem : ISystem { [BurstCompile] public void OnUpdate(ref SystemState state) { // Pre-allocate before parallel job state.EnsureBufferCapacity(8192); var writer = state.GetEventWriter(); var job = new ParallelWriteJob { writer = writer }; job.ScheduleParallel().Complete(); } } public struct ParallelWriteJob : IJobEntity { public EventWriter writer; void Execute() { // Safe because capacity was pre-allocated writer.WriteNoResize(new MyEvent()); } } ``` -------------------------------- ### Obtain EventWriter and write an event Source: https://github.com/annulusgames/entitiesevents/blob/main/README.md Retrieves an EventWriter from the Events container and writes a new event. This is how data is added to the container. ```cs // Obtain EventWriter and write var eventWriter = events.GetWriter(); eventWriter.Write(new MyEvent()); ``` -------------------------------- ### Update Method Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/UnsafeEvents.md Swaps internal buffers and clears the oldest one. This is crucial for managing event data over time. ```APIDOC ## Update Method ### Description Swaps internal buffers and clears the oldest one. ### Signature ```csharp [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Update() ``` ### Return void ### Throws/Rejects - `InvalidOperationException` if buffer is null ### Example ```csharp var unsafeEvents = new UnsafeEvents(512, Allocator.Persistent); while (gameRunning) { var reader = unsafeEvents.GetReader(); foreach (var evt in reader.Read()) { } unsafeEvents.Update(); } unsafeEvents.Dispose(); ``` ``` -------------------------------- ### Custom Event Queue Implementation with UnsafeEventWriter Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/UnsafeEventWriter.md Illustrates how UnsafeEventWriter can be used within a custom event queue implementation for specialized scenarios. This pattern bypasses safety checks for direct control over event handling. ```csharp public class CustomEventQueue { readonly UnsafeEvents events; public void Send(MyEvent evt) { var writer = events.GetWriter(); writer.Write(evt); } public void ProcessFrame() { events.Update(); } } ``` -------------------------------- ### Handle Negative Initial Capacity in Events Constructor Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/errors.md Catch ArgumentOutOfRangeException when a negative initial capacity is provided to the Events constructor. Ensure the capacity is non-negative. ```csharp try { int capacity = GetUserConfiguredCapacity(); if (capacity < 0) capacity = 512; // Validate var events = new Events(capacity, Allocator.Persistent); } catch (ArgumentOutOfRangeException ex) { Debug.LogError($"Out of range: {ex.Message}"); // Use fallback value } ``` -------------------------------- ### EventWriter Constructor Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/EventWriter.md Creates a new EventWriter instance from an existing Events container. This is the primary way to obtain a writer for publishing events. ```csharp public EventWriter(in Events events) ``` -------------------------------- ### EventInstance Structure Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/types.md Represents a single event with its payload and a sequence identifier. Used to track consumed events by comparing sequence IDs. ```csharp public readonly struct EventInstance where T : unmanaged { public readonly T value; public readonly uint id; public EventInstance(in T value, uint id); } ``` -------------------------------- ### Write Method Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/UnsafeEventWriter.md Writes an event value to the current frame's buffer, resizing the buffer if necessary. This is the primary method for adding events when safety checks are not required. ```APIDOC ## Write(in T value) ### Description Writes an event value to the current frame's buffer, resizing if necessary. ### Method `Write(in T value)` ### Parameters #### Path Parameters - **value** (T) - Required - The event to write ### Response #### Success Response (void) void ### Request Example ```csharp var writer = unsafeEvents.GetWriter(); writer.Write(new MyEvent { id = 42, data = 3.14f }); ``` ``` -------------------------------- ### Dispose Event Containers with try/finally Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/errors.md Always ensure event containers are disposed of properly to prevent resource leaks. Use a try/finally block for reliable disposal. ```csharp var events = new Events(512, Allocator.Persistent); try { } finally { events.Dispose(); } ``` -------------------------------- ### Pre-allocate Buffer Capacity for Parallel Writes Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/README.md Ensures sufficient capacity in the event buffer before performing parallel writes to prevent potential buffer overflows. This is crucial when multiple systems might write to the same event type concurrently. ```csharp state.EnsureBufferCapacity(estimatedMax); var writer = state.GetEventWriter(); ``` -------------------------------- ### Update Events Container for Frame-Based Processing Source: https://github.com/annulusgames/entitiesevents/blob/main/_autodocs/api-reference/Events.md Demonstrates calling `Update()` once per frame to swap internal buffers and clear the oldest, ensuring proper event lifecycle management in a custom system or loop. ```csharp // In a custom system or manual update loop var events = new Events(512, Allocator.Persistent); while (true) { // Process events... var reader = events.GetReader(); foreach (var evt in reader.Read()) { } // Update for next frame events.Update(); } events.Dispose(); ```