### Complete Smart Blobber Example for DigitsBlob Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Core/Smart Blobbers.md This is a comprehensive example demonstrating the creation of a Smart Blobber for a DigitsBlob type. It includes all necessary components, authoring, baking logic, and the system for processing blob requests. ```csharp using Unity.Burst; using Unity.Collections; using Unity.Entities; using UnityEngine; using Latios; using Latios.Authoring; public struct DigitsBlob { public int value; public BlobArray digits; } public struct DigitsBlobReference : IComponentData { public BlobAssetReference blob; } [DisallowMultipleComponent] public class DigitsAuthoring : MonoBehaviour { public int value = 381; public int[] digits = { 3, 8, 1 }; } [TemporaryBakingType] public struct DigitsBakeItem : ISmartBakeItem { SmartBlobberHandle blob; public bool Bake(DigitsAuthoring authoring, IBaker baker) { baker.AddComponent(); blob = baker.RequestCreateBlobAsset(authoring.value, authoring.digits); return true; } public void PostProcessBlobRequests(EntityManager entityManager, Entity entity) { entityManager.SetComponentData(entity, new DigitsBlobReference { blob = blob.Resolve(entityManager) }); } } public class DigitsBaker : SmartBaker { } // Begin Custom Smart Blobber code public static class DigitsSmartBlobberBakerExtensions { public static SmartBlobberHandle RequestCreateBlobAsset(this IBaker baker, int value, int[] digits) { return baker.RequestCreateBlobAsset(new DigitsSmartBlobberRequestFilter { value = value, digits = digits }); } } [TemporaryBakingType] internal struct DigitsValueInput : IComponentData { public int value; } [TemporaryBakingType] internal struct DigitsElementInput : IBufferElementData { public int digit; } public struct DigitsSmartBlobberRequestFilter : ISmartBlobberRequestFilter { public int value; public int[] digits; public bool Filter(IBaker baker, Entity blobBakingEntity) { if (digits == null) return false; baker.AddComponent(blobBakingEntity, new DigitsValueInput { value = value }); var buffer = baker.AddBuffer(blobBakingEntity).Reinterpret(); foreach (var digit in digits) buffer.Add(digit); return true; } } [UpdateInGroup(typeof(Latios.Authoring.Systems.SmartBlobberBakingGroup))] [BurstCompile] public partial struct DigitsSmartBlobberSystem : ISystem { public void OnCreate(ref SystemState state) { new SmartBlobberTools().Register(state.World); } [BurstCompile] public void OnDestroy(ref SystemState state) { } [BurstCompile] public void OnUpdate(ref SystemState state) { new Job().ScheduleParallel(); } [WithEntityQueryOptions(EntityQueryOptions.IncludeDisabledEntities | EntityQueryOptions.IncludePrefab)] [BurstCompile] partial struct Job : IJobEntity { public void Execute(ref SmartBlobberResult result, in DigitsValueInput valueInput, in DynamicBuffer bufferInput) { var builder = new BlobBuilder(Allocator.Temp); ref var root = ref builder.ConstructRoot(); root.value = valueInput.value; builder.ConstructFromNativeArray(ref root.digits, bufferInput.Reinterpret().AsNativeArray()); var typedBlob = builder.CreateBlobAssetReference(Allocator.Persistent); result.blob = Unity.Entities.LowLevel.Unsafe.UnsafeUntypedBlobAssetReference.Create(typedBlob); } } } ``` -------------------------------- ### Batch Transform System Setup Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Transforms/Writing QVVS Transforms in Parallel.md Sets up a system to query entities with WorldTransform and prepares for parallel transform updates. ```csharp partial struct BatchTransformSystem : ISystem { EntityQuery m_query; [BurstCompile] public void OnCreate(ref SystemState state) { m_query = state.Fluent().With().Build(); } [BurstCompile] public void OnUpdate(ref SystemState state) { var transformHandle = new TransformAspectParallelChunkHandle(SystemAPI.GetComponentLookup(false), SystemAPI.GetComponentTypeHandle(true), SystemAPI.GetBufferLookup(true), SystemAPI.GetBufferLookup(true), SystemAPI.GetEntityStorageInfoLookup(), ref state); state.Dependency = transformHandle.ScheduleChunkCaptureForQuery(m_query, state.Dependency); state.Dependency = transformHandle.ScheduleChunkGrouping(state.Dependency); state.Dependency = new BatchJob { transformHandle = transformHandle }.ScheduleParallel(transformHandle, state.Dependency); } // The job type is IJobParallelForDefer, which creates an index per group of chunks [BurstCompile] struct BatchJob : IJobParallelForDefer { public TransformAspectParallelChunkHandle transformHandle; HasChecker rootReferenceChecker; public void Execute(int index) { // If we know we are processing a single chunk of entities that are root or solo entities, // then we can linearly iterate through the chunk without having to concern ourselves with top-down hierarchy ordering. int numChunksInGroup = transformHandle.GetChunkCountForIJobParallelForDeferIndex(index); transformHandle.GetChunkInGroupForIJobParallelForDefer(index, 0, out var chunk, out _, out _, out _); if (numChunksInGroup == 1 && !rootReferenceChecker[chunk]) { UpdateChunkWithOnlySoloAndRootEntitiesFast(index); return; } // We need to concern ourselves with top-down ordering, as multiple entities in this group might come from the same hierarchy. UpdateGroupInBatches(index, numChunksInGroup); } void UpdateChunkWithOnlySoloAndRootEntitiesFast(int groupIndex) { transformHandle.GetChunkInGroupForIJobParallelForDefer(groupIndex, 0, out var chunk, out var unfilteredChunkIndex, out var useEnabledMask, out var chunkEnabledMask); transformHandle.SetActiveChunkForIJobParallelForDefer(groupIndex, 0); var enumerator = new ChunkEntityEnumerator(useEnabledMask, chunkEnabledMask, chunk.Count); while (enumerator.NextEntityIndex(out int entityIndexInChunk)) { TransformAspect transform = transformHandle[entityIndexInChunk]; transform.TranslateWorld(transform.forwardDirection * 0.01f); } } void UpdateGroupInBatches(int groupIndex, int numChunksInGroup) { // Count the number of entities to process so we can stackalloc the right size. int numTransforms = 0; for (int i = 0; i < numChunksInGroup; i++) { ``` -------------------------------- ### Example Component Data Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Core/Collection and Managed Struct Components.md A standard IComponentData struct example. ```csharp public struct Pipe : IComponentData { public float timeUntilNextEmission; } ``` -------------------------------- ### IJobEntity Example for Parallel Transforms Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Transforms/QVVS V2 Upgrade Guide.md This snippet demonstrates the setup and execution of a parallel transform job using IJobEntity and TransformAspectParallelChunkHandle. It requires scheduling three separate jobs: collection, grouping, and processing. Ensure you use ScheduleByRef() for the initial job and ScheduleChunkGrouping and ScheduleParallel for the subsequent steps. ```csharp [BurstCompile] public void OnUpdate(ref SystemState state) { var job = new Job { transformHandle = new TransformAspectParallelChunkHandle(SystemAPI.GetComponentLookup(false), SystemAPI.GetComponentTypeHandle(true), SystemAPI.GetBufferLookup(true), SystemAPI.GetBufferLookup(true), SystemAPI.GetEntityStorageInfoLookup(), ref state) }; job.ScheduleByRef(); // You MUST use ScheduleByRef() specifically here. IJobEntity.Execute() does NOT run here. state.Dependency = job.transformHandle.ScheduleChunkGrouping(state.Dependency); state.Dependency = job.GetTransformsScheduler().ScheduleParallel(state.Dependency); // IJobEntity.Execute() actually runs here. } [WithAll(typeof(WorldTransform))] [BurstCompile] partial struct Job : IJobEntity, IJobEntityChunkBeginEnd, IJobChunkParallelTransform { public TransformAspectParallelChunkHandle transformHandle; public ref TransformAspectParallelChunkHandle transformAspectHandleAccess => ref transformHandle.RefAccess(); public void Execute([EntityIndexInChunk] int indexInChunk, in TimeToLive timeToLive, in SpawnPointAnimationData data) { float growFactor = math.unlerp(data.growStartTime, data.growEndTime, timeToLive.timeToLive); growFactor = math.select(growFactor, 1f, data.growStartTime == data.growEndTime); float shrinkFactor = math.unlerp(0f, data.shrinkStartTime, timeToLive.timeToLive); float factor = math.saturate(math.min(growFactor, shrinkFactor)); bool isGrowing = growFactor < shrinkFactor; float growRadians = math.lerp(-data.growSpins, 0f, factor); float shrinkRadians = math.lerp(data.shrinkSpins, 0f, factor); float rads = math.select(shrinkRadians, growRadians, isGrowing); var transform = transformHandle[indexInChunk]; transform.localRotation = quaternion.Euler(0f, 0f, rads); transform.localScale = math.max(factor, 0.001f); } public bool OnChunkBegin(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask) { return transformHandle.OnChunkBegin(in chunk, unfilteredChunkIndex, useEnabledMask, chunkEnabledMask); } public void OnChunkEnd(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask, bool chunkWasExecuted) { } } ``` -------------------------------- ### EnableCommandBuffer Usage Example Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Optimization Adventures/Part 4 - Command Buffers 1.md Demonstrates the usage of EnableCommandBuffer to add entities to be enabled and then playback the commands. This includes setting components and managing a list of enabled ships. ```csharp var ecb = new EnableCommandBuffer(Allocator.TempJob); Entities.WithAll().ForEach((Entity entity, ref SpawnPayload payload, in SpawnTimes times) => { if (times.enableTime <= 0f && payload.disabledShip != Entity.Null) { var ship = payload.disabledShip; ecb.Add(ship); SetComponent(ship, GetComponent(entity)); SetComponent(ship, GetComponent(entity)); payload.disabledShip = Entity.Null; enabledShipList.Add(ship); } }).Run(); ecb.Playback(EntityManager, GetBufferFromEntity(true)); ecb.Dispose(); ``` -------------------------------- ### InstantiateCommandBuffer Example Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Core/Custom Command Buffers and SyncPointPlaybackSystem.md Demonstrates using InstantiateCommandBuffer and DestroyCommandBuffer in a parallel job to spawn explosion prefabs when a ship's health drops to zero. Requires WorldTransform component for instantiation. ```csharp using Unity.Burst; using Unity.Entities; using Unity.Transforms; using Latios.Authoring.Systems; using Latios.Authoring.Systems.SyncPointPlayback; [BurstCompile] public void OnUpdate(ref SystemState state) { var icb = latiosWorld.syncPoint.CreateInstantiateCommandBuffer().AsParallelWriter(); var dcb = latiosWorld.syncPoint.CreateDestroyCommandBuffer().AsParallelWriter(); new Job { dcb = dcb, icb = icb }.ScheduleParallel(); } [BurstCompile] [WithChangeFilter(typeof(ShipHealth))] partial struct Job : IJobEntity { public InstantiateCommandBuffer.ParallelWriter icb; public DestroyCommandBuffer.ParallelWriter dcb; public void Execute(Entity entity, [ChunkIndexInQuery] int chunkIndexInQuery, in ShipHealth health, in ShipExplosionPrefab explosionPrefab, in WorldTransform worldTransform) { if (health.health <= 0f) { dcb.Add(entity, chunkIndexInQuery); if (explosionPrefab.explosionPrefab != Entity.Null) icb.Add(explosionPrefab.explosionPrefab, worldTransform, chunkIndexInQuery); } } } ``` -------------------------------- ### Initialize DamageCollidingShipsProcessor Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Psyshock Physics/Getting Started - Part 3.md Set up the DamageCollidingShipsProcessor by getting the necessary component lookups. This processor is designed for parallel execution. ```csharp var processor = new DamageCollidingShipsProcessor { shipHealthLookup = SystemAPI.GetComponentLookup(), shipDamageLookup = SystemAPI.GetComponentLookup() }; ``` -------------------------------- ### Clock Test Fixed Tick System Setup Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Tech Adventures/Part 12 - Networking 2.md Initializes the FixedStepClockMemory component on the world blackboard entity. This system is Burst compiled and requires matching queries. ```csharp [RequireMatchingQueriesForUpdate] [BurstCompile] public partial struct ClockTestFixedTickSystem : ISystem { LatiosWorldUnmanaged latiosWorld; public void OnCreate(ref SystemState state) { latiosWorld = state.GetLatiosWorldUnmanaged(); latiosWorld.worldBlackboardEntity.AddComponent(); } [BurstCompile] public void OnUpdate(ref SystemState state) { latiosWorld.worldBlackboardEntity.SetComponentData(new FixedStepClockMemory { deltaTime = Time.DeltaTime, elapsedTime = Time.ElapsedTime, }); foreach ((var flag, var clock, var interpolatedClock) in Query, RefRW >().WithAll()) { if (flag.run == 0) continue; interpolatedClock.ValueRW.capturedPreviousFixedStep = clock.ValueRO.fixedStep; ``` -------------------------------- ### Clock Test Input System Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Tech Adventures/Part 12 - Networking 2.md System to capture spacebar input to trigger the start of the clock. Requires matching queries for update and is Burst compiled. ```csharp [RequireMatchingQueriesForUpdate] [BurstCompile] public partial struct ClockTestInputSystem : ISystem { public void OnUpdate(ref SystemState state) { var kb = UnityEngine.InputSystem.Keyboard.current; if (kb.spaceKey.wasPressedThisFrame) { foreach (var input in Query >().WithAll()) input.ValueRW.startClock.Set(); } } } ``` -------------------------------- ### Initialize RigidBodyPhysicsSystem Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Tech Adventures/Part 8 - Road to Physics Simulation 6.md Sets up the main physics system, including obtaining a reference to the Latios World. The OnUpdate method is currently empty. ```csharp using FreeParking; using FreeParking.Systems; using Latios; using Latios.Psyshock; using Latios.Transforms; using Unity.Burst; using Unity.Collections; using Unity.Entities; using Unity.Jobs; using Unity.Mathematics; using static Unity.Entities.SystemAPI; namespace DreamingImLatios.PsyshockRigidBodies.Systems { [BurstCompile] public partial struct RigidBodyPhysicsSystem : ISystem { LatiosWorldUnmanaged latiosWorld; [BurstCompile] public void OnCreate(ref SystemState state) { latiosWorld = state.GetLatiosWorldUnmanaged(); } [BurstCompile] public void OnUpdate(ref SystemState state) { } } [UpdateInGroup(typeof(FixedStepSimulationSystemGroup))] public partial class PsyshockRigidBodiesSuperSystem : RootSuperSystem { DevDungeonSystemFilter m_filter = new DevDungeonSystemFilter("DreamingImLatios/PsyshockRigidBodies"); protected override void CreateSystems() { GetOrCreateAndAddUnmanagedSystem(); GetOrCreateAndAddUnmanagedSystem(); } public override void OnNewScene() => m_filter.OnNewScene(); public override bool ShouldUpdateSystem() => m_filter.ShouldUpdateSystem(sceneBlackboardEntity); } } ``` -------------------------------- ### Generated Latios Framework Collection Component Code Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Tech Adventures/Part 2 - Source Generators 2.md This C# code represents the output of a source generator for a collection component. It includes nested structs and classes, along with BurstCompile attributes and methods for handling component data and cleanup. This is an example of successfully generated code after resolving initial setup and formatting issues. ```csharp namespace TestLibrary.ActionableNamespaces.TotalChaos { public partial class Class1 { internal partial struct NestedStruct { static partial class NestedStaticClass { [global::System.Runtime.CompilerServices.CompilerGenerated] [global::Unity.Burst.BurstCompile] public partial struct MyCollectionComponent3 : global::Latios.InternalSourceGen.StaticAPI.ICollectionComponentSourceGenerated { public struct ExistComponent : IComponentData { } public struct CleanupComponent : ICleanupComponentData, global::Latios.InternalSourceGen.StaticAPI.ICollectionComponentCleanup { public static global::Unity.Burst.FunctionPointer GetBurstDispatchFunctionPtr() { return global::Unity.Burst.BurstCompiler.CompileFunctionPointer(BurstDispatch); } public static global::System.Type GetCollectionComponentType() => typeof(MyCollectionComponent3); } public ComponentType componentType => ComponentType.ReadOnly(); public ComponentType cleanupType => ComponentType.ReadOnly(); [global::Unity.Burst.BurstCompile] public static unsafe void BurstDispatch(void* context, int operation) { global::Latios.InternalSourceGen.StaticAPI.BurstDispatchCollectionCollectionComponent(context, operation); } } } } } } ``` -------------------------------- ### EnableCommandBuffer Usage Example Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Core/Custom Command Buffers and SyncPointPlaybackSystem.md Demonstrates how to use EnableCommandBuffer within a system's OnUpdate method to enable entities. Requires Allocator.TempJob and manual playback with EntityManager and BufferFromEntity. Dispose the command buffer after playback. ```csharp using Unity.Entities; using Unity.Jobs; using Unity.Burst; using Unity.Collections; using Latios.Frameworks.CommandBuffers; using Latios.Frameworks.Aspects; using Unity.Transforms; [BurstCompile] public void OnUpdate(ref SystemState state) { var ecb = new EnableCommandBuffer(Allocator.TempJob); foreach ((var payload, var times, var entity) in Query, RefRO >().WithEntityAccess()) { if (times.ValueRO.enableTime <= 0f && payload.ValueRO.disabledShip != Entity.Null) { var ship = payload.ValueRO.disabledShip; ecb.Add(ship); var entityTransform = GetComponent(entity); var shipTransform = GetAspect(ship); shipTransform.worldRotation = entityTransform.rotation; shipTransform.worldPosition = entityTransform.position; payload.ValueRW.disabledShip = Entity.Null; } } ecb.Playback(state.EntityManager, GetBufferLookup(true)); ecb.Dispose(); } ``` -------------------------------- ### Pyshock Job for Bullet Collision Layer Setup Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Optimization Adventures/Part 14 - Operation Reduction 1.md This IJobEntity is responsible for initial setup of collider bodies for bullet collision. It processes entity, world transform, collider, and previous transform data to create a ColliderBody entry. ```csharp [BurstCompile] partial struct Job : IJobEntity { public NativeArray bodies; public void Execute(Entity entity, [EntityIndexInQuery] int entityInQueryIndex, in WorldTransform worldTransform, in Collider collider, in PreviousTransform previousPosition) { CapsuleCollider capsule = collider; float tailLength = math.distance(worldTransform.position, previousPosition.position); capsule.pointA = capsule.pointB; capsule.pointA.z -= math.max(tailLength, math.EPSILON); bodies[entityInQueryIndex] = new ColliderBody { collider = capsule, entity = entity, transform = worldTransform.worldTransform }; } } ``` -------------------------------- ### Get Chunk for an Entity Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Optimization Adventures/Part 4 - Command Buffers 1.md Retrieves the ArchetypeChunk for a given entity. This is a key method for accessing chunk-related data. ```csharp public ArchetypeChunk GetChunk(Entity entity) { var ecs = GetCheckedEntityDataAccess()->EntityComponentStore; var chunk = ecs->GetChunk(entity); return new ArchetypeChunk(chunk, ecs); } ``` -------------------------------- ### Minimum LatiosWorld Initialization Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Installation and Compatibility Guide.md These lines are the minimum requirements to create a working LatiosWorld when integrating with an existing ICustomBootstrap. Ensure these are called within your Initialize() method. ```csharp var world = new LatiosWorld(defaultWorldName); world.initializationSystemGroup.SortSystems(); return true; ``` -------------------------------- ### Create and Initialize PairStream Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Psyshock Physics/Getting Started - Part 4.md Instantiate a PairStream with collision layers and get a parallel writer for the FindPairs operation. ```csharp var pairStream = new PairStream(playerLayer, state.WorldUpdateAllocator); var findPairsProcessor = new PlayerVsZoneFindPairsProcessor { pairStream = pairStream.AsParallelWriter() }; ``` -------------------------------- ### Instantiate Prefabs with NewICB Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Optimization Adventures/Part 18 - Command Buffers 3.md Instantiates prefabs using the new implementation of Instant Command Buffer (ICB). This method is used with unique prefabs and their counts, showing a slightly different approach to accessing prefab data. ```csharp // Step 4: Instantiate the prefabs var instantiatedEntities = new NativeArray(count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var typesWithDataToAdd = BuildComponentTypesFromFixedList(icb.m_state->typesWithData); int startIndex = 0; for (int i = 0; i < uniquePrefabs.Length; i++) { var uniquePrefab = uniquePrefabs[i]; var firstEntity = em.Instantiate(uniquePrefab.prefab); em.AddComponent(firstEntity, typesWithDataToAdd); em.AddComponent(firstEntity, icb.m_state->tagsToAdd); instantiatedEntities[startIndex] = firstEntity; startIndex++; if (uniquePrefab.count - 1 > 0) { var subArray = instantiatedEntities.GetSubArray(startIndex, uniquePrefab.count - 1); em.Instantiate(firstEntity, subArray); startIndex += subArray.Length; } } ``` -------------------------------- ### ComponentBroker APIs for Single-Threaded Jobs Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Core/Component Broker.md Commonly used ComponentBroker APIs for single-threaded jobs. No special setup is required. ```csharp public bool Exists(Entity entity) public bool Has(Entity entity) public RefRO GetRO(Entity entity) where T : unmanaged, IComponentData public RefRW GetRW(Entity entity) where T : unmanaged, IComponentData public DynamicBuffer GetBuffer(Entity entity) where T : unmanaged, IBufferElementData public EnabledRefRO GetEnabledRO(Entity entity) where T : unmanaged, IEnableableComponent public EnabledRefRW GetEnabledRW(Entity entity) where T : unmanaged, IEnableableComponent public bool TryGetSharedComponent(Entity entity, out T sharedComponentOrDefault) where T : unmanaged, ISharedComponentData ``` -------------------------------- ### Initialize Component Broker with Builder Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Core/Component Broker.md Initialize the ComponentBroker in OnCreate() using a ComponentBrokerBuilder. Use .With() calls to specify components and buffers, and .Build() to finalize. Dispose the broker in OnDestroy(). ```csharp public void OnCreate(ref SystemState state) { componentBroker = new ComponentBrokerBuilder(Allocator.Temp) .With(false) // read-write component .With(true) // read-only component .With(false) // read-write buffer .With(true) // read-only buffer .With(true) // shared components are always read-only and ignore your parameter .WithTransformAspect() // extension method for TransformAspect .With(false) // you can specify up to 5 types in one With<>() call .Build(ref state, Allocator.Persistent); } public void OnDestroy(ref SystemState state) => componentBroker.Dispose(); ``` -------------------------------- ### ContactOnB Span Conversion Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Tech Adventures/Part 8 - Road to Physics Simulation 6.md Provides a method to get a Span from a collection of contacts, useful for efficient iteration. ```csharp public Span AsSpan() { fixed (ContactOnB* ptr = &this[0]) return new Span(ptr, contactCount); } ``` -------------------------------- ### SystemRng Job Implementation Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Calci/Rng and RngToolkit.md Implement IJobEntityChunkBeginEnd for your job. Invoke SystemRng.BeginChunk() in OnChunkBegin() and then call random functions directly on the SystemRng instance. ```csharp [BurstCompile] partial struct Job : IJobEntity, IJobEntityChunkBeginEnd { public SystemRng rng; public bool OnChunkBegin(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask) { rng.BeginChunk(unfilteredChunkIndex); return true; } public void Execute(ref AiSearchAndDestroyPersonality personality, in AiSearchAndDestroyPersonalityInitializerValues initalizer) { personality.targetLeadDistance = rng.NextFloat(initalizer.targetLeadDistanceMinMax.x, initalizer.targetLeadDistanceMinMax.y); } public void OnChunkEnd(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask, bool chunkWasExecuted) { } } ``` -------------------------------- ### Instantiate Prefabs with OldICB Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Optimization Adventures/Part 18 - Command Buffers 3.md Instantiates prefabs using the old implementation of Instant Command Buffer (ICB). This method is used when dealing with sorted prefabs and their counts. ```csharp // Step 4: Instantiate the prefabs var instantiatedEntities = new NativeArray(count, Allocator.Temp, NativeArrayOptions.UninitializedMemory); var typesWithDataToAdd = BuildComponentTypesFromFixedList(icb.m_state->typesWithData); int startIndex = 0; for (int i = 0; i < sortedPrefabs.Length; i++) { var firstEntity = em.Instantiate(sortedPrefabs[i]); em.AddComponent(firstEntity, typesWithDataToAdd); em.AddComponent(firstEntity, icb.m_state->tagsToAdd); instantiatedEntities[startIndex] = firstEntity; startIndex++; if (sortedPrefabCounts[i] - 1 > 0) { var subArray = instantiatedEntities.GetSubArray(startIndex, sortedPrefabCounts[i] - 1); em.Instantiate(firstEntity, subArray); startIndex += subArray.Length; } } ``` -------------------------------- ### Define RigidBody Component Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Tech Adventures/Part 8 - Road to Physics Simulation 6.md Defines the basic component data for a rigid body. This is a starting point and will be expanded as needed. ```csharp using Unity.Collections; using Unity.Entities; using Unity.Mathematics; namespace DreamingImLatios.PsyshockRigidBodies { struct RigidBody : IComponentData { // } } ``` -------------------------------- ### Instantiate and Set Component Data for Bullet Prefab Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Optimization Adventures/Part 4 - Command Buffers 1.md This snippet demonstrates instantiating a bullet prefab and setting its Rotation and Translation components. It calculates the bullet's position based on the gun's transform and the bullet's half-length. This involves multiple EntityCommandBuffer commands per bullet. ```csharp var bullet = ecb.Instantiate(entityInQueryIndex, bulletPrefab.bulletPrefab); CapsuleCollider collider = GetComponent(bulletPrefab.bulletPrefab); float halfLength = math.distance(collider.pointA, collider.pointB) / 2f + collider.radius; var ltw = GetComponent(gunPoints[i].gun); var rot = quaternion.LookRotationSafe(ltw.Forward, ltw.Up); ecb.SetComponent(entityInQueryIndex, bullet, new Rotation { Value = rot }); ecb.SetComponent(entityInQueryIndex, bullet, new Translation { Value = ltw.Position + math.forward(rot) * halfLength}); ``` -------------------------------- ### Define StartClockInput Component Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Tech Adventures/Part 12 - Networking 2.md Defines an input component to trigger the start of a clock. It uses InputEvent for discrete actions. ```csharp public struct StartClockInput : IComponentData { public InputEvent startClock; } ``` -------------------------------- ### Add GamePreTransformSuperSystem Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Core/How To Make an N - 1 Render Loop.md This SuperSystem should be added to the `SimulationSystemGroup` and run before `TransformSuperSystem` to handle pre-transform logic in N-1 rendering. ```csharp [UpdateInGroup(typeof(SimulationSystemGroup))] [UpdateBefore(typeof(TransformSuperSystem))] public class GamePreTransformSuperSystem : RootSuperSystem { protected override void CreateSystems() { } } ``` -------------------------------- ### SecondPassForEachPairProcessor Implementation Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Psyshock Physics/Getting Started - Part 4.md Implement IForEachPairProcessor to process pairs after the FindPairs operation. This example calculates player points based on zone data. ```csharp struct SecondPassForEachPairProcessor : IForEachPairProcessor { public PhysicsComponentLookup playerPointsLookup; [ReadOnly] public ComponentLookup zonePlayerCountLookup; [ReadOnly] public ComponentLookup zonePointsLookup; public void Execute(ref PairStream.Pair pair) { var pointsInZone = zonePointsLookup[pair.entityB].pointsPerFrame; var playerCountInZone = zonePlayerCountLookup[pair.entityB].playerCount; playerPointsLookup.GetRW(pair.entityA).ValueRW.points += pointsInZone / playerCountInZone; } ``` -------------------------------- ### IJobEntity for Parallel Root Transforms Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Transforms/Writing QVVS Transforms in Parallel.md An `IJobEntity` job that processes root entities in parallel using `TransformAspectRootHandle`. It includes `IJobEntityChunkBeginEnd` for chunk setup and teardown. ```csharp [BurstCompile] [WithAll(typeof(WorldTransform))] [WithNone(typeof(RootReference))] partial struct EntityRootTransformsJob : IJobEntity, IJobEntityChunkBeginEnd { public TransformAspectRootHandle transformHandle; public bool OnChunkBegin(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask) { transformHandle.SetupChunk(in chunk); return true; } public void OnChunkEnd(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask, bool chunkWasExecuted) { } public void Execute([EntityIndexInChunk] int indexInChunk) { var transform = transformHandle[indexInChunk]; transform.TranslateWorld(transform.forwardDirection * 0.01f); } } ``` -------------------------------- ### Add GamePostTransformSuperSystem Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Core/How To Make an N - 1 Render Loop.md This SuperSystem should be added to the `SimulationSystemGroup` and run after `TransformSuperSystem` to handle post-transform logic in N-1 rendering. ```csharp [UpdateInGroup(typeof(SimulationSystemGroup))] [UpdateAfter(typeof(TransformSuperSystem))] public class GamePostTransformSuperSystem : RootSuperSystem { protected override void CreateSystems() { } } ``` -------------------------------- ### Get Parent Entity Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Transforms/QVVS Transforms V2 Design Discussion.md Retrieves the parent entity of a given entity. Requires lookups for root references, entity storage info, and entities in hierarchy. ```csharp public static Entity ParentFrom(Entity entity, ref ComponentLookup rootReferenceLookupRO, ref EntityStorageInfoLookup entityStorageInfoLookup, ref BufferLookup entityInHierarchyLookupRO) => throw new System.NotImplementedException(); ``` -------------------------------- ### Controlling System Updates based on Blackboard Entity Component Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Core/Blackboard Entities.md This example shows how to use a component on the world blackboard entity to conditionally update systems. The BlackboardSuperSystem checks the count of CompA before updating. ```csharp public struct CompA : IComponentData { public int count; } public partial class BlackboardSuperSystem : SuperSystem { protected override void CreateSystems() { GetOrCreateAndAddSystem(); GetOrCreateAndAddUnmanagedSystem(); } public override bool ShouldUpdateSystem() { return worldBlackboardEntity.GetComponentData().count < 10; } } ``` -------------------------------- ### Define IFindPairsProcessor for Body vs Body Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Tech Adventures/Part 8 - Road to Physics Simulation 6.md Defines a basic structure for processing pairs of rigid bodies. This is the starting point for custom pair-finding logic. ```csharp struct FindBodyVsBodyProcessor : IFindPairsProcessor { public void Execute(in FindPairsResult result) { // } } ``` -------------------------------- ### NewICB: Prefix-Summing Unique Prefabs for Ranges Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Optimization Adventures/Part 18 - Command Buffers 3.md This C# code snippet calculates the start index for each unique prefab by performing a prefix sum on their counts. This prepares the data for assigning command ranges. ```csharp int running = 0; for (int i = 0; i < uniquePrefabs.Length; i++) { ref var u = ref uniquePrefabs.ElementAt(i); u.start = running; running += u.count; u.count = 0; } ``` -------------------------------- ### Full FindNeighborsSystem Implementation Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Psyshock Physics/Recipes/How To Find All Tagged Neighbors Within a Radius.md A complete system demonstrating how to find tagged neighbors within a radius. It sets up colliders, builds a collision layer, and uses FindPairs with a custom processor to add neighbors. ```csharp public class FindNeighborsSystem : SystemBase { EntityQuery m_query; const float SEARCH_RADIUS = 10f; protected override void OnUpdate() { var sphereCollider = new SphereCollider(float3.zero, SEARCH_RADIUS / 2f); var bodies = new NativeArray(m_query.CalculateEntityCount(), Allocator.TempJob); Entities.WithAll().ForEach((Entity entity, int entityInQueryIndex, ref DynamicBuffer neighborBuffer, in Translation translation) => { neighborBuffer.Clear(); bodies[entityInQueryIndex] = new ColliderBody { collider = sphereCollider, entity = entity, transform = new RigidTransform(quaternion.identity, translation.Value) }; }).WithStoreEntityQueryInField(ref m_query).ScheduleParallel(); Dependency = Physics.BuildCollisionLayer(bodies).ScheduleParallel(out var layer, Allocator.TempJob, Dependency); Dependency = bodies.Dispose(Dependency); var processor = new FindNeighborsProcessor { neighborLookup = GetBufferLookup() }; Dependency = Physics.FindPairs(layer, processor).ScheduleParallel(Dependency); Dependency = layer.Dispose(Dependency); } struct FindNeighborsProcessor : IFindPairsProcessor { public PhysicsBufferLookup neighborLookup; public void Execute(in FindPairsResult result) { if (Physics.DistanceBetween(result.colliderA, result.transformA, result.colliderB, result.transformB, 0f, out _)) { neighborLookup[result.entityA].Add(new Neighbor { prefabEntity = new EntityWith { entity = result.entityB } }); neighborLookup[result.entityB].Add(new Neighbor { prefabEntity = new EntityWith { entity = result.entityA } }); } } } } ``` -------------------------------- ### Clear Most Significant Bits in BitField64 Source: https://github.com/dreaming381/latios-framework-documentation/blob/main/Optimization Adventures/Part 17 - Command Buffers 2.md Resets bits from the most significant bit downwards up to a specified start index. This is used to clear out data that has been moved or processed. ```csharp static void ClearMsbBits(int startIndex, ref BitField64 lower, ref BitField64 upper) { if (startIndex <= 64) { upper = default; lower.Value &= (1ul << startIndex) - 1; } else upper.Value &= (1ul << (startIndex - 64)) - 1; } ```