### Unity MonoBehaviour ECS Example (C#) Source: https://context7.com/genaray/arch.docs/llms.txt A C# example demonstrating how to integrate Arch ECS within a Unity MonoBehaviour. It shows world creation, entity population with components (Transform2D, Sprite), and updating entities using a query within the MonoBehaviour's lifecycle methods (Start, Update, OnDestroy). ```csharp using UnityEngine; using Arch.Core; public record struct Transform2D(float X, float Y, float Rotation); public record struct Sprite(string TextureName); public class ECSManager : MonoBehaviour { private World _world; private QueryDescription _renderQuery; void Start() { _world = World.Create(); _renderQuery = new QueryDescription().WithAll(); // Create entities for (int i = 0; i < 1000; i++) { _world.Create( new Transform2D(Random.Range(-10f, 10f), Random.Range(-10f, 10f), 0), new Sprite("enemy") ); } } void Update() { float dt = Time.deltaTime; _world.Query(in _renderQuery, (ref Transform2D transform, ref Sprite sprite) => { // Update game logic transform.Rotation += dt * 90f; }); } void OnDestroy() { _world?.Dispose(); } } ``` -------------------------------- ### Define a System with Queries in C# Source: https://github.com/genaray/arch.docs/blob/main/extensions/page-3/arch.system.md Demonstrates how to define a system that inherits from BaseSystem and uses QueryDescription to process entities with specific components. It includes an example of updating entity positions based on their velocity. ```csharp public class MovementSystem : BaseSystem { private QueryDescription _desc = new QueryDescription().WithAll(); public MovementSystem(World world) : base(world) {} // Can be called once per frame public override void Update(in float deltaTime) { // Run query, can also run multiple queries inside the update method World.Query(in _desc, (ref Position pos, ref Velocity vel) => { pos.X += vel.X; pos.Y += vel.Y; }); } } ``` -------------------------------- ### Install Arch ECS using .NET CLI Source: https://github.com/genaray/arch.docs/blob/main/README.md Installs the Arch ECS library version 2.1.0-beta into a C# project using the .NET CLI. This command adds the necessary package reference to your project file. ```sh dotnet add PROJECT package Arch --version 2.1.0-beta ``` -------------------------------- ### Customizing World Creation (C#) Source: https://github.com/genaray/arch.docs/blob/main/documentation/world.md Shows how to create a customized World instance with specific initial capacities for chunks, entities per chunk, archetype array, and entity count. These parameters guide Arch's memory allocation. ```csharp var customizedWorld = World.Create( chunkSizeInBytes: 16_382, // The base size of each chunk minimumAmountOfEntitiesPerChunk: 100, // The base amount of entities per chunk archetypeCapacity: 8, // The initial size of the archetype array entityCapacity: 64 // The initial amount of entities ); ``` -------------------------------- ### C# Event Handling with Arch.EventBus Source: https://github.com/genaray/arch.docs/blob/main/extensions/page-3/arch.eventbus.md Demonstrates how to set up and use Arch.EventBus for event notification. It shows how to define event receivers using instance and static methods, annotate them with the [Event] attribute, and send events using EventBus.Send. The example highlights the use of structs as events and the optional 'order' parameter for controlling execution sequence. ```csharp public partial class MyInstanceReceiver { public MysInstanceReceiver(){ Hook(); } // To start listening. [Event] public void OnShootEvent(ref ShootEvent @event){ // Handle } } public static class SomeEventHandler{ [Event(order: 2)] public static void OnShootFireBullets(ref ShootEvent @event){ // ref, none, in supported and all types as a event. Only one param! // Do stuff } [Event(order: 1)] public static void OnShootFireBullets(ref ShootEvent @event){ // ref, none, in supported and all types as a event. Only one param! // Do stuff } } var shootEvent = new ShootEvent(); EventBus.Send(ref shootEvent); // Broadcasts the event to all annotated methods wherever they are. ``` -------------------------------- ### Parallel Query Execution with C# JobScheduler Source: https://context7.com/genaray/arch.docs/llms.txt Utilizes Arch's zero-allocation JobScheduler for concurrent entity processing across multiple CPU cores. This example shows setting up the scheduler, creating entities, and executing parallel queries using lambdas, inline structs, and low-level chunk jobs. Dependencies include Arch.Core and JobScheduler. ```csharp using Arch.Core; using JobScheduler; using System.Runtime.CompilerServices; public record struct Position(float X, float Y); public record struct Velocity(float Dx, float Dy); var world = World.Create(); // Setup JobScheduler var jobScheduler = new JobScheduler.JobScheduler( new JobScheduler.JobScheduler.Config { ThreadPrefixName = "GameWorker", ThreadCount = 0, // 0 = auto-detect CPU cores MaxExpectedConcurrentJobs = 64, StrictAllocationMode = false } ); world.SharedJobScheduler = jobScheduler; // Create many entities for (var i = 0; i < 100_000; i++) { world.Create(new Position(i, i), new Velocity(1, 1)); } var queryDesc = new QueryDescription().WithAll(); // Parallel query with lambda (blocks until complete) world.ParallelQuery(in queryDesc, (ref Position pos, ref Velocity vel) => { pos.X += vel.Dx; pos.Y += vel.Dy; }); // Parallel inline query (faster) public struct ParallelMovement : IForEach { [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Update(ref Position pos, ref Velocity vel) { pos.X += vel.Dx; pos.Y += vel.Dy; } } world.InlineParallelQuery(in queryDesc); // Low-level parallel chunk processing public struct ChunkProcessor : IChunkJob { public void Execute(ref Chunk chunk) { ref var positions = ref chunk.GetFirst(); ref var velocities = ref chunk.GetFirst(); foreach (var entity in chunk) { ref var pos = ref Unsafe.Add(ref positions, entity); ref var vel = ref Unsafe.Add(ref velocities, entity); pos.X += vel.Dx; pos.Y += vel.Dy; } } } world.InlineParallelChunkQuery(in queryDesc, new ChunkProcessor()); // Cleanup jobScheduler.Dispose(); ``` -------------------------------- ### Manual Chunk Iteration with C# Source: https://context7.com/genaray/arch.docs/llms.txt Demonstrates manual, low-level iteration over entity chunks for maximum control and performance. This method is suitable for SIMD operations and custom multithreading strategies. It involves getting references to component arrays within each chunk and iterating through entities. ```csharp using Arch.Core; using System.Runtime.CompilerServices; public record struct Position(float X, float Y); public record struct Velocity(float Dx, float Dy); var world = World.Create(); var queryDesc = new QueryDescription().WithAll(); // Get query and iterate chunks manually var query = world.Query(in queryDesc); foreach (ref var chunk in query.GetChunkIterator()) { // Get first element references for the arrays var refs = chunk.GetFirst(); // Iterate each entity in the chunk foreach (var entityIndex in chunk) { ref var pos = ref Unsafe.Add(ref refs.t0, entityIndex); ref var vel = ref Unsafe.Add(ref refs.t1, entityIndex); pos.X += vel.Dx; pos.Y += vel.Dy; } } // Alternative: Get arrays directly for SIMD operations foreach (ref var chunk in query.GetChunkIterator()) { var positions = chunk.GetArray(); var velocities = chunk.GetArray(); var count = chunk.Size; for (var i = 0; i < count; i++) { positions[i].X += velocities[i].Dx; positions[i].Y += velocities[i].Dy; } } ``` -------------------------------- ### C# Source-Generated Query Example Source: https://github.com/genaray/arch.docs/blob/main/documentation/optimizations/query-techniques.md This C# code snippet demonstrates a source-generated query using Arch.Extended. It showcases the use of attributes like [Query] and [Data], along with aggressive inlining for performance. The query allows passing parameters by reference (ref, in, out) and utilizes a Move function for entity manipulation. ```csharp [Query] // [All<...>, Any<...>, None<...>] to filter // [Parallel] for multithreading [MethodImpl(MethodImplOptions.AggressiveInlining)] public void MoveEntity([Data] ref float time, ref Position pos, ref Velocity vel) { Move(ref pos, ref vel, ref time); } ``` -------------------------------- ### Batch Component Operations for Entity in C# Source: https://github.com/genaray/arch.docs/blob/main/documentation/entity.md Shows how to add, get, and set multiple components on an entity simultaneously using generic overloads. This method is efficient for managing several components at once. ```csharp // Adding components to our dwarf in batch (We could also pass them as parameters) dwarf.Add(); // Receiving components in batch and modifying them var equipment = dwarf.Get(); equipment.t0.Durability = 100f; equipment.t1.Defence = 100f; equipment.t3.Weight = 0.5f; // Overwriting components since, why not? dwarf.Set(new DwarfArmor(110f), new LeatherBoots(Sole.GRIPPY)); // Dwarf happy now, lets ensure he does not wear any other gear by removing it if(dwarf.Has()){ dwarf.Remove(); } ``` -------------------------------- ### World-Based Entity Component Access (C#) Source: https://github.com/genaray/arch.docs/blob/main/documentation/optimizations/pure_ecs.md Illustrates the correct way to interact with entity components using the 'world' object in a PURE_ECS environment. This approach is necessary because the 'Entity' struct's methods are inaccessible. It shows how to check for components, get component references, and set component values via the world. ```csharp // Making our dwarf teleport if(world.Has(gimli)){ ref var pos = ref world.Get(gimli); world.Set(gimli, TeleportRandomlyNear(ref pos)); } ``` -------------------------------- ### Generated Component Registration Module (C#) Source: https://github.com/genaray/arch.docs/blob/main/extensions/page-3/arch.aot.sourcegenerator.md Shows the C# code generated by Arch.AOT.SourceGenerator. This static class, marked with [ModuleInitializer], automatically registers components upon application start. ```csharp namespace Arch.AOT.SourceGenerator { internal static class GeneratedComponentRegistry { [ModuleInitializer] public static void Initialize() { ComponentRegistry.Add(new ComponentType(ComponentRegistry.Size + 1, typeof(Velocity), Unsafe.SizeOf(), false); ArrayRegistry.Add(); ComponentRegistry.Add(new ComponentType(ComponentRegistry.Size + 1, typeof(Transform), Unsafe.SizeOf(), false); ArrayRegistry.Add(); } } } ``` -------------------------------- ### Setup JobScheduler for Multithreading Source: https://github.com/genaray/arch.docs/blob/main/documentation/optimizations/multithreading.md Initializes and configures the JobScheduler for use with the Arch world. This involves setting thread names, thread count (0 for runtime determination), maximum concurrent jobs, and allocation mode. The configured scheduler is then assigned to the world and must be disposed of at the end of its lifecycle. ```csharp var jobScheduler = new JobScheduler( new JobScheduler.Config { ThreadPrefixName = "Arch.Samples", ThreadCount = 0, MaxExpectedConcurrentJobs = 64, StrictAllocationMode = false, } ); world.SharedJobScheduler = jobScheduler; // To dispose the JobScheduler at the end of the lifecycle. jobScheduler.Dispose(); ``` -------------------------------- ### Create Entities with Different Structures (C#) Source: https://github.com/genaray/arch.docs/blob/main/documentation/archetypes-and-chunks.md Illustrates how entities with different component structures are placed into separate archetypes, even if they share some common components. This C# example shows a standard dwarf and a mining dwarf with an additional Pickaxe component. ```csharp var dwarf = world.Create(new Dwarf(), new Position(), new Velocity()); var miningDwarf = world.Create(new Dwarf(), new Position(), new Velocity(), new Pickaxe()); ``` -------------------------------- ### Manage Systems with Groups in C# Source: https://github.com/genaray/arch.docs/blob/main/extensions/page-3/arch.system.md Shows how to create a World instance, group multiple systems (including custom ones like MovementSystem, PhysicsSystem, etc.) into a Group, and manage their lifecycle (Initialize, BeforeUpdate, Update, AfterUpdate, Dispose). ```csharp // Create a world and a group of systems which will be controlled var world = World.Create(); var _systems = new Group( new MovementSystem(world), new PhysicsSystem(world), new DamageSystem(world), new WorldGenerationSystem(world), new OtherGroup(world) ); _systems.Initialize(); // Inits all registered systems _systems.BeforeUpdate(in deltaTime); // Calls .BeforeUpdate on all systems ( can be overriden ) _systems.Update(in deltaTime); // Calls .Update on all systems ( can be overriden ) _systems.AfterUpdate(in deltaTime); // Calls .AfterUpdate on all System ( can be overriden ) _systems.Dispose(); // Calls .Dispose on all systems ( can be overriden ) ``` -------------------------------- ### Basic Arch ECS Usage in C# Source: https://github.com/genaray/arch.docs/blob/main/README.md Demonstrates the fundamental usage of the Arch ECS library in C#. It includes defining components, creating a world and an entity, and querying entities with specific components to perform an action (moving entities based on position and velocity). ```csharp using Arch; // Components public record struct Position(float X, float Y); public record struct Velocity(float Dx, float Dy); // Create a world and an entity with position and velocity. using var world = World.Create(); var player = world.Create(new Position(0,0), new Velocity(1,1)); // Enumerate all entities with Position & Velocity to move them var query = new QueryDescription().WithAll(); world.Query(in query, (Entity entity, ref Position pos, ref Velocity vel) => { pos.X += vel.Dx; pos.Y += vel.Dy; Console.WriteLine($"Moved player: {entity.Id}"); }); ``` -------------------------------- ### Access and Modify Components in Arch ECS Source: https://context7.com/genaray/arch.docs/llms.txt Shows how to access, modify, and check for the presence of components on entities using Arch ECS. It covers using `Get`, `Set`, `Has`, `TryGet`, and batch operations for component management. ```csharp using Arch.Core; public record struct Position(float X, float Y); public record struct Velocity(float Dx, float Dy); public record struct Inventory(int Slots); var world = World.Create(); var entity = world.Create(new Position(0, 0), new Velocity(1, 1)); // Get component reference and modify ref var position = ref entity.Get(); position.X += 10; position.Y += 5; // Set component to new value entity.Set(new Velocity(2, 2)); // Check if entity has component before accessing if (entity.Has()) { ref var inventory = ref entity.Get(); inventory.Slots += 10; } // TryGet for safe access ref var vel = ref entity.TryGet(out var hasVelocity); if (hasVelocity) { vel.Dx *= 2; } // Batch operations - get multiple components at once var components = entity.Get(); components.t0.X += components.t1.Dx; components.t0.Y += components.t1.Dy; ``` -------------------------------- ### Create and Manage World Instances in Arch ECS Source: https://context7.com/genaray/arch.docs/llms.txt Demonstrates how to create and manage World instances, the central containers for entities in Arch ECS. It shows basic and customized world creation, along with lifecycle management methods like TrimExcess, Dispose, and Destroy. ```csharp using Arch.Core; // Create a basic world var world = World.Create(); // Create a customized world with specific configuration var customWorld = World.Create( chunkSizeInBytes: 16_382, // Base size of each chunk minimumAmountOfEntitiesPerChunk: 100, // Minimum entities per chunk archetypeCapacity: 8, // Initial archetype array size entityCapacity: 64 // Initial entity capacity ); // Lifecycle management world.TrimExcess(); // Free unused memory world.Dispose(); // Clear all entities World.Destroy(world); // Complete destruction ``` -------------------------------- ### World Lifecycle Management (C#) Source: https://github.com/genaray/arch.docs/blob/main/documentation/world.md Demonstrates the basic lifecycle operations for a World instance in C#. This includes creating a new world, freeing unused memory, disposing of the world, and a complete destruction process. ```csharp var world = World.Create(); // Creating a world full of life world.TrimExcess(); // Frees unused memory world.Dispose(); // Clearing the world like God in the First Testament World.Destroy(world); // Doomsday ``` -------------------------------- ### Modify Entity Components in C# Source: https://github.com/genaray/arch.docs/blob/main/documentation/entity.md Illustrates how to modify existing components of an entity and add or remove new components. It shows getting a component by reference, setting a new component, and conditionally adding/removing components like Pickaxe. ```csharp // Create our beloved dwarf var dwarf = world.Create(new Dwarf("Gimli"), new Position(0,0), new Velocity()); // Telepor the dwarf ref var position = ref dwarf.Get(); position.X++; position.Y++; // Force him to move on its own dwarf.Set(new Velocity(1,1)); // Give the dwarf a pickaxe and make him sad by taking it away if(!dwarf.Has()) dwarf.Add(new Pickaxe()); dwarf.Remove(); ``` -------------------------------- ### Delete Entities Randomly in Query (C#) - UNSAFE Source: https://github.com/genaray/arch.docs/blob/main/examples-and-guidelines/page-2.md An example of attempting to delete entities randomly within a query. This is unsafe because deleting an entity can cause the last entity of its archetype to replace it, leading to potential double processing or missed iterations. ```csharp world.Query(queryDesc, (in Entity entity, ref Dwarf dwarf) => { if(!CanDeleteDwarf()) return; // A random chance world.Destroy(RandomDwarf()); }); ``` -------------------------------- ### Access Entity Metadata with EntityData (C#) Source: https://github.com/genaray/arch.docs/blob/main/documentation/optimizations/entitydata.md Demonstrates how to use EntityData to access and modify entity metadata. It shows retrieving entity data, getting and setting components, and accessing archetype and chunk information. This method is faster than traditional lookups. ```csharp var entity = world.Create(new Dwarf(), new Pickaxe()); ref var data = ref world.GetEntityData(entity); // Less lookups, faster then doing it the traditional way ref var pickaxe = ref data.Get(); pickaxe.HP = 100; data.Set(new Pickaxe()); // Access archetype & chunk var archetype = data.Archetype; ref var chunk = ref data.Chunk; ``` -------------------------------- ### Organize Logic with BaseSystem in C# Source: https://context7.com/genaray/arch.docs/llms.txt Provides a BaseSystem class for organizing queries into reusable systems. Systems can be grouped and executed together within a game loop. Requires Arch.System extension. ```csharp using Arch.Core; using Arch.System; public record struct Position(float X, float Y); public record struct Velocity(float Dx, float Dy); public record struct Health(int Value); // Define a system public class MovementSystem : BaseSystem { private QueryDescription _query = new QueryDescription().WithAll(); public MovementSystem(World world) : base(world) { } public override void Update(in float deltaTime) { World.Query(in _query, (ref Position pos, ref Velocity vel) => { pos.X += vel.Dx * deltaTime; pos.Y += vel.Dy * deltaTime; }); } } public class HealthSystem : BaseSystem { public HealthSystem(World world) : base(world) { } public override void Update(in float deltaTime) { var query = new QueryDescription().WithAll(); World.Query(in query, (ref Health health) => { // Regenerate health over time health.Value = Math.Min(100, health.Value + 1); }); } } // Group and execute systems var world = World.Create(); var systems = new Group( new MovementSystem(world), new HealthSystem(world) ); // Game loop systems.Initialize(); while (gameRunning) { float deltaTime = GetDeltaTime(); systems.BeforeUpdate(in deltaTime); systems.Update(in deltaTime); systems.AfterUpdate(in deltaTime); } systems.Dispose(); ``` -------------------------------- ### Create Entities with Components in Arch ECS Source: https://context7.com/genaray/arch.docs/llms.txt Illustrates how to create entities and attach components using the Arch ECS library. It covers creating entities with component instances, default values, bulk creation, and reserving capacity for performance. ```csharp using Arch.Core; // Define components as structs public record struct Position(float X, float Y); public record struct Velocity(float Dx, float Dy); public record struct Health(int Value); public record struct Player(string Name); var world = World.Create(); // Create entity with component instances var player = world.Create( new Player("Hero"), new Position(0, 0), new Velocity(1, 1), new Health(100) ); // Create entity with default component values var enemy = world.Create(); // Bulk create multiple entities with same components world.Create(1_000, new Position(0, 0), new Velocity(0, 0), new Health(50)); // Reserve capacity before bulk creation for performance world.EnsureCapacity(100_000); for (var i = 0; i < 100_000; i++) { world.Create(new Position(i, i), new Velocity(1, 0), new Health(100)); } ``` -------------------------------- ### Get ComponentType using typeof - C# Source: https://github.com/genaray/arch.docs/blob/main/documentation/utilities/non-generic-api.md Retrieves the ComponentType for a given component type using the typeof operator. This is a non-generic way to access component metadata, useful when the component type is determined at runtime. It's slightly slower than the generic variant but offers flexibility. ```csharp var componentType = ComponentRegistry.GetComponentType(typeof(Dwarf)); var sameComponentType = (ComponentType)typeof(Dwarf); ``` -------------------------------- ### Access and Manage Components (C#) Source: https://github.com/genaray/arch.docs/blob/main/documentation/utilities/component-registration.md Demonstrates how to check if a component is registered, retrieve its metadata, replace it with a new variant (e.g., for hot-reloading), and remove it from the registry. ```csharp // Checks whether the component is registered var hasInventoryRegistered = ComponentRegistry.Has(); // Try-Get if(hasInventoryRegistered) { ComponentRegistry.TryGet(out var componentType); Console.WriteLine(componentType); } // Replaces the component with a new variant e.g. hot Hot-Loading ComponentRegistry.Replace(); // Removes the Component from registration ComponentRegistry.Remove(); ``` -------------------------------- ### Custom Binary Serializer for Sprites in Arch.Persistence Source: https://github.com/genaray/arch.docs/blob/main/extensions/page-3/arch.persistence.md Illustrates creating a custom MessagePack formatter for a 'Sprite' type when using Arch.Persistence's binary serialization. This allows for optimized binary representation of custom data. ```csharp public class SpriteSerializer : IMessagePackFormatter { public void Serialize(ref MessagePackWriter writer, Sprite value, MessagePackSerializerOptions options) { // Your logic } public Sprite Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options) { // Your logic } } ``` -------------------------------- ### Entity Referencing and Versioning in C# Source: https://github.com/genaray/arch.docs/blob/main/documentation/entity.md Explains how to reference entities, emphasizing the importance of the `Entity.Version` property for correct comparisons, especially when entities are recycled. Direct comparison of `Entity` structs is recommended over comparing IDs alone. ```csharp var dwarf = world.Create(); world.Destroy(dwarf); var recycledDwarf = world.Create(); Console.WriteLine($"Dwarf-Id: {dwarf.Id} and RecycledDwarf-Id: {recycledDwarf.Id}"); Console.WriteLine(dwarf == recycledDwarf); // False, same Id but different versions ``` -------------------------------- ### Compile-Time Static Component Access (C#) Source: https://github.com/genaray/arch.docs/blob/main/documentation/utilities/component-registration.md Provides compile-time static access to component metadata without runtime lookups, improving efficiency. Supports individual components or signatures for multiple components. ```csharp var componentType = Component.ComponentType; ``` ```csharp var signature = Component.Signature; ``` -------------------------------- ### Parallel Query Execution with Multithreading in C# Source: https://github.com/genaray/arch.docs/blob/main/extensions/page-3/arch.system.sourcegenerator.md Shows how to enable parallel query execution using Arch's multithreading support. By setting `Parallel = true` in the `[Query]` attribute, the query can be executed concurrently on multiple threads, improving performance for suitable operations. ```csharp [Query(Parallel = true)] // Method is being called by Archs multithreading. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void MoveEntities([Data] in float time, ref Position pos, ref Velocity vel){ pos.X += time * vel.X; pos.Y += time * vel.Y; } ``` -------------------------------- ### Basic Query Execution in C# Source: https://github.com/genaray/arch.docs/blob/main/documentation/optimizations/query-techniques.md Executes a query using a simple delegate for iterating over entities with Position and Velocity components. This method is concise and suitable for prototyping but can be slower due to delegate overhead and lacks component security. ```csharp World.Query(in desc, (ref Position pos, ref Velocity vel) => { Move(ref pos, ref vel); }); ``` -------------------------------- ### Manually Calling Generated Queries in C# Source: https://github.com/genaray/arch.docs/blob/main/extensions/page-3/arch.system.sourcegenerator.md Shows how to manually invoke the query methods generated by Arch.System.SourceGenerator. After the source generator processes the [Query] attributes, specific query methods (e.g., MoveEntityQuery) are created. These can be called directly with the World instance to execute the defined entity processing logic. ```csharp var world = World.Create(); var movementSystem = new MovementSystem(world); myMovementSystem.Update(deltaTime); // Calls both Querys in order automatically myMovementSystem.MoveEntityQuery(world); // Manually calling the querys myMovementSystem.StopDeadEntitiesQuery(world); ``` -------------------------------- ### Serialize World and Entities to Binary (C#) Source: https://context7.com/genaray/arch.docs/llms.txt Employs Arch.Persistence for efficient binary serialization and deserialization of worlds and entities. This format is more compact and faster than JSON for storage and transfer. It requires the `Arch.Persistence` namespace and `ArchBinarySerializer` class. ```csharp using Arch.Core; using Arch.Persistence; public record struct Position(float X, float Y); public record struct Velocity(float Dx, float Dy); public record struct Player(string Name); var world = World.Create(); world.Create(new Player("Hero"), new Position(100, 50), new Velocity(1, 0)); world.Create(new Position(0, 0), new Velocity(0, 1)); // Binary Serialization (more efficient) var binarySerializer = new ArchBinarySerializer(); // Serialize to bytes byte[] worldBytes = binarySerializer.Serialize(world); // Deserialize from bytes var restoredWorld = binarySerializer.Deserialize(worldBytes); // Single entity binary serialization var entity = world.Create(new Player("NPC"), new Position(0, 0)); byte[] entityBytes = binarySerializer.Serialize(world, entity); binarySerializer.Deserialize(world, entityBytes); ``` -------------------------------- ### Generate Queries in Custom C# Classes Source: https://github.com/genaray/arch.docs/blob/main/extensions/page-3/arch.system.sourcegenerator.md Demonstrates how to define queries within custom C# classes, including static classes. The `[Query]` attribute is used to mark methods for query generation. This allows for queries to be defined outside of the `BaseSystem`. ```csharp public partial class MyQueries{ [Query] [MethodImpl(MethodImplOptions.AggressiveInlining)] public void MoveEntities([Data] in float time, ref Position pos, ref Velocity vel){ pos.X += time * vel.X; pos.Y += time * vel.Y; } [Query] [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void DamageEntities(ref Hitted hit, ref Health health){ health.value -= hit.value; } } ``` -------------------------------- ### Record and Playback Entity Operations with CommandBuffer (C#) Source: https://github.com/genaray/arch.docs/blob/main/documentation/utilities/commandbuffer.md This snippet demonstrates how to use CommandBuffer in C# to record operations on entities, such as adding components, setting component values, and creating new entities. The recorded commands can then be played back to a world, optionally with disposal. ```csharp var dwarf = world.Create(new Dwarf(), new Position(), new Velocity()); var commandBuffer = new CommandBuffer(); commandBuffer.Add(dwarf, new Pickaxe()); commandBuffer.Set(dwarf, new Position(10,10)); var nonExistingDwarf = commandBuffer.Create(new Signature(typeof(Dwarf), typeof(Position), typeof(Velocity))); commandBuffer.PlayBack(world, disposal = true); ``` -------------------------------- ### Inspect Entity Components in C# Source: https://github.com/genaray/arch.docs/blob/main/documentation/entity.md Demonstrates methods for inspecting an entity's components, including retrieving all component types and all component instances. It also shows how to print the entity's representation. ```csharp var types = dwarf.GetComponentTypes(); // Getting all types, readonly var components = dwarf.GetComponents(); // Getting all components by boxing Console.WriteLine(dwarf); // Printing the entity ``` -------------------------------- ### Create Multiple Entities with Reserved Memory Source: https://github.com/genaray/arch.docs/blob/main/documentation/optimizations/batch-and-bulk.md Creates entities and fills the pre-reserved memory space. This method is efficient for creating a large number of entities with identical components. ```csharp world.EnsureCapacity(1_000_000); for(var index = 0; index < 1_000_000; index++){ var dwarf = world.Create(signature); } ``` -------------------------------- ### Batch and Bulk Entity Operations with C# Source: https://context7.com/genaray/arch.docs/llms.txt Demonstrates efficient mass entity modifications using batch and bulk operations in Arch.Core. This includes bulk creation, adding/setting/removing components for multiple entities matching a query, and destroying entities. These operations are more performant than individual entity modifications. ```csharp using Arch.Core; public record struct Position(float X, float Y); public record struct Velocity(float Dx, float Dy); public record struct Armor(int Defense); public record struct Dead(); var world = World.Create(); // Bulk create entities world.Create(10_000, new Position(0, 0), new Velocity(1, 1)); // Add components to all matching entities var allMoving = new QueryDescription().WithAll().WithNone(); world.Add(in allMoving, new Armor(50)); // Set component values for all matching entities var withArmor = new QueryDescription().WithAll(); world.Set(in withArmor, new Armor(100)); // Remove components from all matching entities var deadEntities = new QueryDescription().WithAll(); world.Remove(in deadEntities); // Destroy all matching entities (memory is retained for reuse) world.Destroy(in deadEntities); // Free unused memory after bulk destruction world.TrimExcess(); ``` -------------------------------- ### Iterate Entities with Specific Components (C#) Source: https://github.com/genaray/arch.docs/blob/main/documentation/query.md Demonstrates how to create a query that targets entities possessing all specified components (Position and Velocity) and iterates over them to update their position. This is useful for scenarios like moving game objects. ```csharp // Creating many different entities for(var index = 0; index < 1_000, index++){ world.Create(new Dwarf(), new Position(0,0), new Velocity(1,1), new Pickaxe()); world.Create(new Elf(), new Position(0,0), new Velocity(1,1), new Bow()); world.Create(new Human(), new Position(0,0), new Velocity(1,1), new Pickaxe(), new Sword()); } // Iterating over all entities that have Position & Velocity to make them move. var movementQuery = new QueryDescription().WithAll(); world.Query(in movementQuery, (Entity entity, ref Position pos, ref Velocity vel) => { pos += vel; Console.WriteLine($"Moved: {entity}"); }); ``` -------------------------------- ### Utilize PURE_ECS Mode for Minimal Entity Footprint (C#) Source: https://context7.com/genaray/arch.docs/llms.txt Demonstrates how to use Arch's PURE_ECS mode, which reduces the entity size to 4 bytes by removing the world reference from the `Entity` struct. All operations must then be performed through the `World` instance, passing the entity identifier. This mode requires enabling the PURE_ECS compiler option. ```csharp using Arch.Core; // With PURE_ECS enabled, Entity struct is only 4 bytes // All operations must go through World instead of Entity public record struct Position(float X, float Y); public record struct Velocity(float Dx, float Dy); var world = World.Create(); var entity = world.Create(new Position(0, 0), new Velocity(1, 1)); // Standard API (without PURE_ECS): // ref var pos = ref entity.Get(); // entity.Set(new Velocity(2, 2)); // if (entity.Has()) { ... } // PURE_ECS API - use World methods with entity parameter: ref var pos = ref world.Get(entity); pos.X += 10; world.Set(entity, new Velocity(2, 2)); if (world.Has(entity)) { ref var position = ref world.Get(entity); position.Y += 5; } // Add/Remove also through World world.Add(entity, new Health(100)); world.Remove(entity); // EntityReference through World var reference = world.Reference(entity); ``` -------------------------------- ### Custom Loop for Manual Query Iteration (C#) Source: https://github.com/genaray/arch.docs/blob/main/documentation/optimizations/pass-on-data.md Illustrates manual iteration over archetypes and chunks for maximum control over data passing and logic execution. This approach is very efficient but requires more boilerplate code. ```csharp var intruderPosition = DetectIntruder(); var queryDesc = new QueryDescription().WithAll(); var query = World.Query(in queryDesc); foreach (ref var chunk in query) { var positions = chunk.GetSpan(); var velocities = chunk.GetSpan(); foreach (var entityIndex in chunk) { ref var pos = ref positions[entityIndex]; ref var vel = ref velocities[entityIndex]; MoveTowards(ref pos, ref vel, intruderPosition); } } ``` -------------------------------- ### Generate Entity Queries with [Query] Attribute in C# Source: https://github.com/genaray/arch.docs/blob/main/extensions/page-3/arch.system.sourcegenerator.md Demonstrates how to use the [Query] attribute in C# to automatically generate query methods for partial classes. These generated methods process entities matching the specified criteria, reducing boilerplate code. The attribute can be applied to methods within classes like BaseSystem, and its parameters and other attributes define the entity filtering logic. ```csharp public partial class MovementSystem : BaseSystem { public MovementSystem(World world) : base(world) {} [Query] [MethodImpl(MethodImplOptions.AggressiveInlining)] public void MoveEntity([Data] in float time, ref Position pos, in Velocity vel) { pos.X += time * vel.X; pos.Y += time * vel.Y; } [Query] [All, Any, None] public void StopDeadEntities(ref Velocity vel) { vel.X = 0; vel.Y = 0; } } ``` -------------------------------- ### Serialize World to Binary with Arch.Persistence Source: https://github.com/genaray/arch.docs/blob/main/extensions/page-3/arch.persistence.md Serializes an entire world object to a byte array using ArchBinarySerializer. This is efficient for storage and network transfer. Custom serializers can be injected. ```csharp var serializer = new ArchBinarySerializer(new SpriteSerializer{GraphicsDevice = GraphicsDevice}, ...); var worldBytes = serializer.Serialize(_world); // Serialize your world to a byte[] _world = serializer.Deserialize(worldBytes ); // Deserialize it from a byte[]. ``` -------------------------------- ### Register Component Generically (C#) Source: https://github.com/genaray/arch.docs/blob/main/documentation/utilities/component-registration.md Registers a component using generic methods, which automatically determine the component's size and reduce boilerplate code. This is equivalent to manual registration but more concise. ```csharp ComponentRegistry.Add(); ``` ```csharp ArrayRegistry.Add(); ``` -------------------------------- ### CommandBuffer - Deferred Entity Operations in C# Source: https://context7.com/genaray/arch.docs/llms.txt Demonstrates using CommandBuffer to record entity operations like setting, adding, and creating components. These operations are deferred and can be executed later, ensuring thread-safe modifications during parallel queries. It handles playback and disposal of commands. ```csharp using Arch.Core; using Arch.Core.CommandBuffer; public record struct Position(float X, float Y); public record struct Velocity(float Dx, float Dy); public record struct Damage(int Amount); public record struct Dead(); var world = World.Create(); var entity = world.Create(new Position(0, 0), new Velocity(1, 1)); // Create command buffer var commandBuffer = new CommandBuffer(); // Record operations (not executed yet) commandBuffer.Set(entity, new Position(100, 100)); commandBuffer.Add(entity, new Damage(50)); // Create entities via buffer (returns a temporary entity reference) var signature = new Signature(typeof(Position), typeof(Velocity)); var bufferedEntity = commandBuffer.Create(signature); // Execute all recorded commands commandBuffer.Playback(world, dispose: true); // Use in parallel queries safely var queryDesc = new QueryDescription().WithAll(); var buffer = new CommandBuffer(); world.ParallelQuery(in queryDesc, (Entity e, ref Position pos, ref Velocity vel) => { if (pos.X > 1000) { // Safe: recording is thread-safe buffer.Add(e, new Dead()); } }); // Execute after query completes buffer.Playback(world); buffer.Dispose(); ``` -------------------------------- ### Subscribe to Arch Entity and Component Events (C#) Source: https://github.com/genaray/arch.docs/blob/main/documentation/utilities/events.md This snippet demonstrates how to subscribe to various entity and component events within the Arch ECS framework. It covers entity creation/destruction and component addition/setting/removal. These subscriptions are called directly after the respective operations, ensuring high efficiency. ```csharp world.SubscribeEntityCreated((Entity entity) => {}); // Listen for entity creation events world.SubscribeEntityDestroyed((Entity entity) => {}); // Listen for entity destruction events world.SubscribeComponentAdded((Entity entity, ref Position _) => {}); // Listen for newly added components world.SubscribeComponentSet((Entity entity, ref Position _) => {}); // Listen for newly set components world.SubscribeComponentRemoved((Entity entity, ref Position _) => {}); // Listen for newly removed components ``` -------------------------------- ### Manage Entity Components Non-Generically - C# Source: https://github.com/genaray/arch.docs/blob/main/documentation/utilities/non-generic-api.md Demonstrates the management of entity components using a non-generic API. This includes retrieving, modifying, adding, and removing components by their type, providing runtime control over entity composition. It showcases practical application of ComponentType and Signature. ```csharp // Create our beloved dwarf var signature = new Signature(typeof(Dwarf), typeof(Position), typeof(Velocity)); var dwarf = world.Create(signature); // Teleport the dwarf var position = dwarf.Get(typeof(Position)); position.X++; position.Y++; // Force him to move on its own dwarf.Set(typeof(Position), position); // Give the dwarf a pickaxe and make him sad by taking it away if(!dwarf.Has(typeof(Pickaxe))) dwarf.Add(typeof(Pickaxe), new Pickaxe()); dwarf.Remove(typeof(Pickaxe)); ``` -------------------------------- ### Filter Entities with an Exact Component Set (C#) Source: https://github.com/genaray/arch.docs/blob/main/documentation/query.md Demonstrates how to define a query that selects entities having an exact set of components (Dwarf, Position, and Velocity), and no others. This is crucial for targeting specific entity types with precise configurations, like a new breed of dwarfs without pickaxes. ```csharp // New breed of dwarfs, too weak to wear pickaxes for(var index = 0; index < 1_000, index++){ world.Create(new Dwarf(), new Position(0,0), new Velocity(1,1)); } // Only targeting entities with exact those components, no more or less. var makeWeakDwarfsExile = new QueryDescription().WithExclusive(); world.Query(in makeWeakDwarfsExile, (Entity entity) => { Exile(entity); }); ``` -------------------------------- ### Custom JSON Serializer for Sprites in Arch.Persistence Source: https://github.com/genaray/arch.docs/blob/main/extensions/page-3/arch.persistence.md Demonstrates how to create a custom JSON formatter for a 'Sprite' type within Arch.Persistence. This allows for specific serialization and deserialization logic for complex or custom types. ```csharp public class SpriteSerializer : IJsonFormatter { public void Serialize(ref JsonWriter writer, Sprite value, IJsonFormatterResolver formatterResolver) { // Your logic } public Sprite Deserialize(ref JsonReader reader, IJsonFormatterResolver formatterResolver) { // Your logic } } ``` -------------------------------- ### Create and Destroy Entity in C# Source: https://github.com/genaray/arch.docs/blob/main/documentation/entity.md Demonstrates the creation of an entity with multiple components (Dwarf, Position, Velocity) and its subsequent destruction. It highlights the basic lifecycle operations for an entity within a world. ```csharp var world = World.Create(); // World must exist somewhere // A dwarf with a string, position and velocity component was born and killed var dwarf = world.Create(new Dwarf("Gimli"), new Position(0,0), new Velocity()); if(dwarf.IsAlive()) world.Destroy(dwarf); ``` -------------------------------- ### Subscribe to Entity Lifecycle Events in C# Source: https://context7.com/genaray/arch.docs/llms.txt Allows subscribing to entity creation and destruction events. Requires the EVENTS preprocessor flag. Events fire immediately after operations like Create, Destroy, Add, Set, and Remove. ```csharp using Arch.Core; public record struct Position(float X, float Y); public record struct Health(int Value); var world = World.Create(); // Subscribe to entity lifecycle events world.SubscribeEntityCreated((Entity entity) => { Console.WriteLine($"Entity {entity.Id} created"); }); world.SubscribeEntityDestroyed((Entity entity) => { Console.WriteLine($"Entity {entity.Id} destroyed"); }); // Subscribe to component events (type-specific) world.SubscribeComponentAdded((Entity entity, ref Position pos) => { Console.WriteLine($"Position added to {entity.Id}"); }); world.SubscribeComponentSet((Entity entity, ref Health health) => { Console.WriteLine($"Health set to {health.Value} on {entity.Id}"); }); world.SubscribeComponentRemoved((Entity entity, ref Position pos) => { Console.WriteLine($"Position removed from {entity.Id}"); }); // Events fire immediately after operations var entity = world.Create(new Position(0, 0)); // Triggers EntityCreated, ComponentAdded entity.Set(new Position(10, 10)); // Triggers ComponentSet entity.Add(new Health(100)); // Triggers ComponentAdded entity.Remove(); // Triggers ComponentRemoved world.Destroy(entity); // Triggers EntityDestroyed ``` -------------------------------- ### Query Entities with QueryDescription Filters Source: https://context7.com/genaray/arch.docs/llms.txt Explains how to define entity selection criteria using QueryDescription and execute queries with World.Query. Supports filtering by components that must be present (WithAll), absent (WithNone), any of (WithAny), or exclusively present (WithExclusive). ```csharp using Arch.Core; public record struct Position(float X, float Y); public record struct Velocity(float Dx, float Dy); public record struct Enemy(); public record struct Dead(); public record struct Flying(); var world = World.Create(); // Create test entities for (var i = 0; i < 1000; i++) { world.Create(new Position(i, i), new Velocity(1, 1)); world.Create(new Position(i, i), new Velocity(1, 1), new Enemy()); } // WithAll - entities MUST have all specified components var movementQuery = new QueryDescription().WithAll(); world.Query(in movementQuery, (ref Position pos, ref Velocity vel) => { pos.X += vel.Dx; pos.Y += vel.Dy; }); // Query with Entity access world.Query(in movementQuery, (Entity entity, ref Position pos, ref Velocity vel) => { pos.X += vel.Dx; Console.WriteLine($"Moved entity {entity.Id}"); }); // WithNone - entities must NOT have specified components var aliveEnemies = new QueryDescription() .WithAll() .WithNone(); world.Query(in aliveEnemies, (ref Position pos) => { // Process only living enemies }); // WithAny - entities must have at least ONE of specified components var flyingOrMoving = new QueryDescription() .WithAny(); world.Query(in flyingOrMoving, (Entity entity) => { // Process entities that can fly OR have velocity }); // WithExclusive - entities must have EXACTLY these components, no more var exactMatch = new QueryDescription() .WithExclusive(); world.Query(in exactMatch, (Entity entity) => { // Only entities with exactly Position and Velocity }); ``` -------------------------------- ### Filter Entities with Any of Multiple Components (C#) Source: https://github.com/genaray/arch.docs/blob/main/documentation/query.md Illustrates creating a query that targets entities possessing at least one of the specified components (Bow or Sword). This is useful for scenarios where any of a set of items triggers an action, such as calling all entities with any weapon to defense. ```csharp // Targets entities with either a bow or sword. So elves and humans. var letElvesAndHumansPatrol = new QueryDescription().WithAny(); world.Query(in movementQuery, (Entity entity) => { ref var bow = entity.TryGet(out var hasBow); ref var sword = entity.TryGet(out var hasSword); if(EnemyNearby()){ if(hasBow) bow.Attack(); if(hasSword) sword.Attack(); } }); ``` -------------------------------- ### Generate Basic Entity Movement Query (C#) Source: https://context7.com/genaray/arch.docs/llms.txt Demonstrates how to generate a query for moving entities based on their position and velocity. The `[Query]` attribute on the `MoveEntities` method triggers the source generator to create an optimized query method. This method requires `deltaTime`, `Position`, and `Velocity` components. ```csharp using Arch.Core; using Arch.System; using Arch.System.SourceGenerator; using System.Runtime.CompilerServices; public record struct Position(float X, float Y); public record struct Velocity(float Dx, float Dy); public record struct Health(int Value); public record struct Dead(); public partial class GameSystems : BaseSystem { public GameSystems(World world) : base(world) { } // Basic query - generates MoveEntitiesQuery method [Query] [MethodImpl(MethodImplOptions.AggressiveInlining)] public void MoveEntities([Data] in float deltaTime, ref Position pos, in Velocity vel) { pos.X += vel.Dx * deltaTime; pos.Y += vel.Dy * deltaTime; } // Query with filters [Query] [All, None] public void RegenerateHealth(ref Health health) { health.Value = Math.Min(100, health.Value + 1); } // Query with entity access [Query] [All] public void CheckDeath(Entity entity, in Health health) { if (health.Value <= 0) { entity.Add(); } } // Parallel query [Query(Parallel = true)] [MethodImpl(MethodImplOptions.AggressiveInlining)] public void ParallelMovement([Data] in float time, ref Position pos, in Velocity vel) { pos.X += vel.Dx * time; pos.Y += vel.Dy * time; } } // Usage var world = World.Create(); var systems = new GameSystems(world); float deltaTime = 0.016f; systems.Update(in deltaTime); // Calls all queries in order // Or call generated queries manually systems.MoveEntitiesQuery(world, deltaTime); systems.RegenerateHealthQuery(world); ```