Esempio n. 1
0
        public unsafe void should_able_to_create_and_fetch_data_from_node_blob()
        {
            Debug.Log($"sizeof NodeA: {sizeof(NodeA.Data)}");
            Debug.Log($"sizeof NodeB: {sizeof(NodeB.Data)}");

            var size = sizeof(NodeA.Data) + sizeof(NodeB.Data);

            using (var blobBuilder = new BlobBuilder(Allocator.Temp))
            {
                ref var blob = ref blobBuilder.ConstructRoot <NodeBlob>();

                var endIndices = blobBuilder.Allocate(ref blob.EndIndices, 3);
                endIndices[0] = 3;
                endIndices[1] = 2;
                endIndices[2] = 3;

                var offsets   = blobBuilder.Allocate(ref blob.Offsets, 3);
                var unsafePtr = (byte *)blobBuilder.Allocate(ref blob.DefaultDataBlob, size).GetUnsafePtr();
                var offset    = 0;
                offsets[0] = offset;
                offsets[1] = offset;
                UnsafeUtilityEx.AsRef <NodeA.Data>(unsafePtr + offset).A = 111;
                offset    += sizeof(NodeA.Data);
                offsets[2] = offset;
                ref var local2 = ref UnsafeUtilityEx.AsRef <NodeB.Data>(unsafePtr + offset);
Esempio n. 2
0
        public unsafe T GetData <T>() where T : struct
        {
            var index = TypeManager.GetTypeIndex <T>();
            var ptr   = Entity.GetComponentDataRawRO(EntityManager, index);

            return(UnsafeUtilityEx.AsRef <T>(ptr));
        }
        public void OnCreate()
        {
            m_TypeArrayIndices = (ushort *)UnsafeUtility.Malloc(sizeof(ushort) * kMaxTypes, 16, Allocator.Persistent);
            UnsafeUtilityEx.MemSet(m_TypeArrayIndices, 0xFF, sizeof(ushort) * kMaxTypes);

#if ENABLE_UNITY_COLLECTIONS_CHECKS
            m_TempSafety = AtomicSafetyHandle.Create();
#endif
            m_ReadJobFences = (JobHandle *)UnsafeUtility.Malloc(sizeof(JobHandle) * kMaxReadJobHandles * kMaxTypes, 16,
                                                                Allocator.Persistent);
            UnsafeUtility.MemClear(m_ReadJobFences, sizeof(JobHandle) * kMaxReadJobHandles * kMaxTypes);

            m_ComponentSafetyHandles =
                (ComponentSafetyHandle *)UnsafeUtility.Malloc(sizeof(ComponentSafetyHandle) * kMaxTypes, 16,
                                                              Allocator.Persistent);
            UnsafeUtility.MemClear(m_ComponentSafetyHandles, sizeof(ComponentSafetyHandle) * kMaxTypes);

            m_JobDependencyCombineBufferCount = 4 * 1024;
            m_JobDependencyCombineBuffer      = (JobHandle *)UnsafeUtility.Malloc(
                sizeof(ComponentSafetyHandle) * m_JobDependencyCombineBufferCount, 16, Allocator.Persistent);

            m_TypeCount     = 0;
            IsInTransaction = false;
            m_ExclusiveTransactionDependency = default(JobHandle);
        }
Esempio n. 4
0
        unsafe public void TestCreateQuad()
        {
            float3[] vertices =
            {
                new float3(-4.5f, 0.0f, 1.0f),
                new float3(3.4f,  0.7f, 1.0f),
                new float3(3.4f,  2.7f, 1.0f),
                new float3(-3.4f, 1.2f, 1.0f)
            };
            float3 normal = math.normalize(math.cross(vertices[2] - vertices[1], vertices[0] - vertices[1]));

            var collider     = PolygonCollider.CreateQuad(vertices[0], vertices[1], vertices[2], vertices[3]);
            var quadCollider = UnsafeUtilityEx.AsRef <PolygonCollider>(collider.GetUnsafePtr());

            Assert.IsFalse(quadCollider.IsTriangle);
            Assert.IsTrue(quadCollider.IsQuad);

            TestUtils.AreEqual(quadCollider.Vertices[0], vertices[0], 1e-3f);
            TestUtils.AreEqual(quadCollider.Vertices[1], vertices[1], 1e-3f);
            TestUtils.AreEqual(quadCollider.Vertices[2], vertices[2], 1e-3f);
            TestUtils.AreEqual(quadCollider.Vertices[3], vertices[3], 1e-3f);
            Assert.AreEqual(2, quadCollider.Planes.Length);
            TestUtils.AreEqual(normal, quadCollider.Planes[0].Normal, 1e-3f);
            TestUtils.AreEqual(-normal, quadCollider.Planes[1].Normal, 1e-3f);
            Assert.AreEqual(ColliderType.Quad, quadCollider.Type);
            Assert.AreEqual(CollisionType.Convex, quadCollider.CollisionType);
        }
Esempio n. 5
0
            public static unsafe void Execute(ref NativeMultiHashMapVisitKeyMutableValueJobStruct <TJob, TKey, TValue> fullData, IntPtr additionalPtr, IntPtr bufferRangePatchData, ref JobRanges ranges, int jobIndex)
            {
                while (true)
                {
                    int begin;
                    int end;

                    if (!JobsUtility.GetWorkStealingRange(ref ranges, jobIndex, out begin, out end))
                    {
                        return;
                    }

                    var buckets  = (int *)fullData.HashMap.m_MultiHashMapData.m_Buffer->buckets;
                    var nextPtrs = (int *)fullData.HashMap.m_MultiHashMapData.m_Buffer->next;
                    var keys     = fullData.HashMap.m_MultiHashMapData.m_Buffer->keys;
                    var values   = fullData.HashMap.m_MultiHashMapData.m_Buffer->values;

                    for (int i = begin; i < end; i++)
                    {
                        int entryIndex = buckets[i];

                        while (entryIndex != -1)
                        {
                            var key = UnsafeUtility.ReadArrayElement <TKey>(keys, entryIndex);

                            fullData.JobData.ExecuteNext(key, ref UnsafeUtilityEx.ArrayElementAsRef <TValue>(values, entryIndex));

                            entryIndex = nextPtrs[entryIndex];
                        }
                    }
                }
            }
Esempio n. 6
0
        public unsafe T GetData <T>() where T : struct
        {
            var index = TypeManager.GetTypeIndex <T>();
            var ptr   = GetPtrByTypeIndexRO(index);

            return(UnsafeUtilityEx.AsRef <T>(ptr));
        }
Esempio n. 7
0
        unsafe public void TestCreateTriangle()
        {
            float3[] vertices =
            {
                new float3(-1.4f, 1.4f, 5.6f),
                new float3(1.4f,  1.4f, 3.6f),
                new float3(0.2f,  1.2f, 5.6f)
            };
            float3 normal = math.normalize(math.cross(vertices[1] - vertices[0], vertices[2] - vertices[0]));

            var collider         = PolygonCollider.CreateTriangle(vertices[0], vertices[1], vertices[2]);
            var triangleCollider = UnsafeUtilityEx.AsRef <PolygonCollider>(collider.GetUnsafePtr());

            Assert.IsTrue(triangleCollider.IsTriangle);
            Assert.IsFalse(triangleCollider.IsQuad);

            TestUtils.AreEqual(triangleCollider.Vertices[0], vertices[0], 1e-3f);
            TestUtils.AreEqual(triangleCollider.Vertices[1], vertices[1], 1e-3f);
            TestUtils.AreEqual(triangleCollider.Vertices[2], vertices[2], 1e-3f);
            Assert.AreEqual(2, triangleCollider.Planes.Length);
            TestUtils.AreEqual(normal, triangleCollider.Planes[0].Normal, 1e-3f);
            TestUtils.AreEqual(-normal, triangleCollider.Planes[1].Normal, 1e-3f);
            Assert.AreEqual(ColliderType.Triangle, triangleCollider.Type);
            Assert.AreEqual(CollisionType.Convex, triangleCollider.CollisionType);
        }
Esempio n. 8
0
 public static void CheckIsUnmanaged <T>()
 {
     if (!UnsafeUtilityEx.IsUnmanaged <T>())
     {
         throw new ArgumentException($"{typeof(T)} used in native collection is not blittable or primitive");
     }
 }
Esempio n. 9
0
            static unsafe void ExecuteInnerLoop(ref JobStruct_Process1 <T, U0> jobData, int begin, int end)
            {
                ComponentChunkCache cache0;

                while (begin != end)
                {
                    jobData.Iterator.Iterator0.UpdateCache(begin, out cache0);
                    var ptr0 = UnsafeUtilityEx.RestrictNoAlias(cache0.CachedPtr);

                    var curEnd = Math.Min(end, cache0.CachedEndIndex);

                    for (var i = begin; i != curEnd; i++)
                    {
#if CSHARP_7_OR_LATER
                        ref var value0 = ref UnsafeUtilityEx.ArrayElementAsRef <U0>(ptr0, i);
                        jobData.Data.Execute(ref value0);
#else
                        var value0 = UnsafeUtility.ReadArrayElement <U0>(ptr0, i);

                        jobData.Data.Execute(ref value0);

                        if (jobData.Iterator.IsReadOnly0 == 0)
                        {
                            UnsafeUtility.WriteArrayElement(ptr0, i, value0);
                        }
#endif
                    }

                    begin = curEnd;
                }
        public static unsafe void PoisonUnusedChunkData(Chunk *chunk, byte value)
        {
            Archetype *archetype       = chunk.Archetype;
            int        chunkBufferSize = Chunk.GetChunkBufferSize(archetype->TypesCount, archetype->NumSharedComponents);
            byte *     numPtr          = &chunk.Buffer.FixedElementField;
            int        count           = chunk.Count;
            int        index           = 0;

            while (true)
            {
                if (index >= (archetype->TypesCount - 1))
                {
                    int num3 = archetype->TypeMemoryOrder[archetype->TypesCount - 1];
                    int num4 = archetype->Offsets[num3] + (count * archetype->SizeOfs[num3]);
                    UnsafeUtilityEx.MemSet((void *)(numPtr + num4), value, chunkBufferSize - num4);
                    return;
                }
                int num6 = archetype->TypeMemoryOrder[index];
                int num7 = archetype->TypeMemoryOrder[index + 1];
                int num8 = archetype->Offsets[num6] + (count * archetype->SizeOfs[num6]);
                int num9 = archetype->Offsets[num7];
                UnsafeUtilityEx.MemSet((void *)(numPtr + num8), value, num9 - num8);
                index++;
            }
        }
Esempio n. 11
0
        protected override unsafe void OnUpdate()
        {
            _mainThreadBlackboard.EntityCommandMainThread.EntityCommandBuffer =
                _endSimulationEntityCommandBufferSystem.CreateCommandBuffer();
            var behaviorTreeJobDeps = new JobHandle();

            Entities.WithoutBurst().ForEach((Entity entity, DynamicBuffer <BehaviorTreeBufferElement> buffers, ref CurrentBehaviorTreeComponent currentBehaviorTree) =>
            {
                _mainThreadBlackboard.Entity = entity;
                _mainThreadBlackboard.EntityCommandMainThread.Entity = entity;
                for (var i = 0; i < buffers.Length; i++)
                {
                    var bufferPtr  = (IntPtr)buffers.GetUnsafeReadOnlyPtr() + UnsafeUtility.SizeOf <BehaviorTreeBufferElement>() * i;
                    ref var buffer = ref UnsafeUtilityEx.AsRef <BehaviorTreeBufferElement>(bufferPtr.ToPointer());
                    if (buffer.RuntimeThread == BehaviorTreeRuntimeThread.MainThread ||
                        buffer.RuntimeThread == BehaviorTreeRuntimeThread.ForceMainThread)
                    {
                        if (buffer.QueryMask.Matches(entity))
                        {
                            var blob = buffers[i].NodeBlob;
                            currentBehaviorTree.Value = bufferPtr;
                            VirtualMachine.Tick(ref blob, ref _mainThreadBlackboard);
                        }
                    }
                    else
                    {
                        // TODO: is this right way to do this? seems not optimize?
                        behaviorTreeJobDeps = JobHandle.CombineDependencies(behaviorTreeJobDeps, buffers[i].Dependency);
                    }
                }
            }).Run();
Esempio n. 12
0
        public void RangeQuery(AABB bounds, NativeList <OctElement <T> > results)
        {
            var targetBounds = new Aabb {
                Min = bounds.Min, Max = bounds.Max
            };
            var outputResults = (UnsafeList *)NativeListUnsafeUtility.GetInternalListDataPtrUnchecked(ref results);

            if (Data->TotalElements > outputResults->Capacity)
            {
                // todo: find out why its possible to return more elements than exists
                // should be able to use 'TotalElements' for capacity here. 10/100 work,
                // but 1000 yields 1012-1018 elements...
                outputResults->Resize <OctElement <T> >(Data->TotalElements * 2);
            }

            var resultsPtr = (byte *)outputResults->Ptr;
            var nodesPtr   = (byte *)Data->Nodes->Ptr;
            var elementPtr = (byte *)Data->Elements->Ptr;
            var quadPtr    = (byte *)Data->Quads->Ptr;

            var quadCount = Data->Quads->Length;
            var maxLeaves = quadCount * 16 * Data->TotalDepth;

            int resultCount  = 0;
            int containCount = 0;
            int overlapCount = 0;

            // Work around c# enforcing use of Span<T>.
            var useStack = maxLeaves <= 256;
            var size     = useStack ? sizeof(int) * maxLeaves : 1;
            var ptr1     = stackalloc int[size];
            var ptr2     = stackalloc int[size];

            size = sizeof(int) * maxLeaves;
            var containOffsets = useStack ? ptr1 : (int *)UnsafeUtility.Malloc(size, sizeof(int), Allocator.Temp);
            var overlapOffsets = useStack ? ptr2 : (int *)UnsafeUtility.Malloc(size, sizeof(int), Allocator.Temp);

            for (int i = 0; i < quadCount; i++)
            {
                QuadGroup quad = *(QuadGroup *)(quadPtr + i * sizeof(QuadGroup));

                bool4 isContainedA       = quad.Bounds.ContainedBy(targetBounds);
                bool4 isOverlapA         = quad.Bounds.OverlappedBy(targetBounds);
                bool4 skipMaskA          = !isContainedA & !isOverlapA;
                bool4 containedLeafMaskA = !skipMaskA & isContainedA;
                bool4 intersectedMaskA   = !containedLeafMaskA & isOverlapA;

                containCount = compress(containOffsets, containCount, quad.Offsets, containedLeafMaskA);
                overlapCount = compress(overlapOffsets, overlapCount, quad.Offsets, intersectedMaskA);
            }

            for (int i = 0; i < containCount; i++)
            {
                ref var node = ref UnsafeUtilityEx.ArrayElementAsRef <OctNode>(nodesPtr, containOffsets[i]);
                var     src  = elementPtr + node.firstChildIndex * UnsafeUtility.SizeOf <OctElement <T> >();
                var     dst  = resultsPtr + resultCount * UnsafeUtility.SizeOf <OctElement <T> >();
                UnsafeUtility.MemCpy(dst, src, node.count * UnsafeUtility.SizeOf <OctElement <T> >());
                resultCount += node.count;
            }
Esempio n. 13
0
 public void FromArrayUnsafe(T[] array)
 {
     Length = array.Length;
     for (var i = 0; i < Length; i++)
     {
         UnsafeUtilityEx.ArrayElementAsRef <T>(ArrayDataPtr, i) = array[i];
     }
 }
    private static unsafe bool IsTrigger(NativeSlice <RigidBody> bodies, int rigidBodyIndex, ColliderKey colliderKey)
    {
        RigidBody hitBody = bodies[rigidBodyIndex];

        hitBody.Collider.Value.GetLeaf(colliderKey, out ChildCollider leafCollider);
        Material material = UnsafeUtilityEx.AsRef <ConvexColliderHeader>(leafCollider.Collider).Material;

        return(material.IsTrigger);
    }
 internal Enumerator(TSource start, long count, TAction action, Allocator allocator)
 {
     this.current   = UnsafeUtilityEx.Malloc <TSource>(1, allocator);
     *this.current  = start;
     this.count     = count;
     this.index     = -1;
     this.action    = action;
     this.allocator = allocator;
 }
Esempio n. 16
0
        public static unsafe T GetData <T>(this IBlackboard bb, ulong componentStableHash, int componentDataOffset)
            where T : struct
        {
            var componentPtr = (byte *)bb.GetPtrRO(componentStableHash);
            // TODO: type safety check
            var dataPtr = componentPtr + componentDataOffset;

            return(UnsafeUtilityEx.AsRef <T>(dataPtr));
        }
Esempio n. 17
0
        public unsafe void SetComponentData <T>(T value) where T : struct, IComponentData
        {
            var typeIndex = TypeManager.GetTypeIndex <T>();

            if (TypeManager.IsZeroSized(typeIndex))
            {
                throw new ArgumentException($"SetComponentData<{typeof(T)}> can not be called with a zero sized component.");
            }
            UnsafeUtilityEx.AsRef <T>(Chunk.GetComponentDataWithTypeRW(Index, typeIndex, GlobalSystemVersion)) = value;
        }
Esempio n. 18
0
 public static unsafe void Allocate <T>(
     this VariableProperty <T> variable
     , ref BlobBuilder builder
     , void *blobVariablePtr
     , INodeDataBuilder self
     , ITreeNode <INodeDataBuilder>[] tree
     ) where T : struct
 {
     variable.Allocate(ref builder, ref UnsafeUtilityEx.AsRef <BlobVariable <T> >(blobVariablePtr), self, tree);
 }
Esempio n. 19
0
        public unsafe T GetComponentData <T>() where T : struct, IComponentData
        {
            var typeIndex = TypeManager.GetTypeIndex <T>();

            if (TypeManager.IsZeroSized(typeIndex))
            {
                throw new ArgumentException($"GetComponentData<{typeof(T)}> can not be called with a zero sized component.");
            }
            return(UnsafeUtilityEx.AsRef <T>(Chunk.GetComponentDataWithTypeRO(Index, typeIndex)));
        }
        unsafe public void TestSphereColliderCreate()
        {
            float3 center         = new float3(-8.45f, 9.65f, -0.10f);
            float  radius         = 0.98f;
            var    collider       = SphereCollider.Create(center, radius);
            var    sphereCollider = UnsafeUtilityEx.AsRef <SphereCollider>(collider.GetUnsafePtr());

            TestUtils.AreEqual(center, sphereCollider.Center, 1e-3f);
            TestUtils.AreEqual(radius, sphereCollider.Radius, 1e-3f);
            Assert.AreEqual(ColliderType.Sphere, sphereCollider.Type);
            Assert.AreEqual(CollisionType.Convex, sphereCollider.CollisionType);
        }
        protected override unsafe void Build(void *dataPtr, BlobBuilder _, ITreeNode <INodeDataBuilder>[] __)
        {
            switch (_source)
            {
            case SourceType.Component:
                break;

            case SourceType.Custom:
            {
                ref var data = ref UnsafeUtilityEx.AsRef <SetTransformRotationWithCustomRotationNode>(dataPtr);
                data.Rotation = quaternion.Euler(CustomRotation);
                break;
            }
Esempio n. 22
0
        public T ReadBlittable <T>() where T : struct
        {
            T val;

            unsafe
            {
                int size = UnsafeUtility.SizeOf <T>();
                NativeSlice <byte> bytes = ReadSlice(size);

                val = UnsafeUtilityEx.AsRef <T>((void *)((byte *)bytes.GetUnsafePtr()));
            }

            return(val);
        }
Esempio n. 23
0
        unsafe public void TestCapsuleColliderCreate()
        {
            float3 v0              = new float3(1.45f, 0.34f, -8.65f);
            float3 v1              = new float3(100.45f, -80.34f, -8.65f);
            float  radius          = 1.45f;
            var    collider        = CapsuleCollider.Create(v0, v1, radius);
            var    capsuleCollider = UnsafeUtilityEx.AsRef <CapsuleCollider>(collider.GetUnsafePtr());

            Assert.AreEqual(ColliderType.Capsule, capsuleCollider.Type);
            Assert.AreEqual(CollisionType.Convex, capsuleCollider.CollisionType);
            TestUtils.AreEqual(v0, capsuleCollider.Vertex0);
            TestUtils.AreEqual(v1, capsuleCollider.Vertex1);
            TestUtils.AreEqual(radius, capsuleCollider.Radius);
        }
Esempio n. 24
0
        public unsafe void TestBoxColliderCreate()
        {
            float3     center       = new float3(-10.10f, 10.12f, 0.01f);
            quaternion orientation  = quaternion.AxisAngle(math.normalize(new float3(1.4f, 0.2f, 1.1f)), 38.50f);
            float3     size         = new float3(0.01f, 120.40f, 5.4f);
            float      convexRadius = 0.0f;
            var        collider     = BoxCollider.Create(center, orientation, size, convexRadius);
            var        boxCollider  = UnsafeUtilityEx.AsRef <BoxCollider>(collider.GetUnsafePtr());

            Assert.AreEqual(center, boxCollider.Center);
            Assert.AreEqual(orientation, boxCollider.Orientation);
            Assert.AreEqual(size, boxCollider.Size);
            Assert.AreEqual(convexRadius, boxCollider.ConvexRadius);
            Assert.AreEqual(CollisionType.Convex, boxCollider.CollisionType);
            Assert.AreEqual(ColliderType.Box, boxCollider.Type);
        }
Esempio n. 25
0
        protected override unsafe void OnUpdate()
        {
            var typeMoveCommand     = GetArchetypeChunkComponentType <MoveCommand>(true);
            var typeDestroyable     = GetArchetypeChunkComponentType <DestroyableComponentData>();
            var typeTicks           = GetArchetypeChunkComponentType <DateTimeTicksToProcess>(true);
            var typeTeamTag         = GetArchetypeChunkComponentType <TeamTag>(true);
            var typePhysicsVelocity = GetArchetypeChunkComponentType <PhysicsVelocity>();
            var currentTicks        = DateTime.Now.Ticks;

            using (var moveCommandChunks = _queryMoveCommand.CreateArchetypeChunkArray(Allocator.TempJob))
                using (var velocitiesChunks = _query.CreateArchetypeChunkArray(Allocator.TempJob))
                {
                    foreach (var moveCommandChunk in moveCommandChunks)
                    {
                        var moveCommands = moveCommandChunk.GetNativeArray(typeMoveCommand);
                        var destroys     = moveCommandChunk.GetNativeArray(typeDestroyable);
                        var ticks        = moveCommandChunk.GetNativeArray(typeTicks);
                        for (var i = 0; i < ticks.Length; i++)
                        {
                            if (ticks[i].Value < currentTicks || destroys[i].ShouldDestroy)
                            {
                                continue;
                            }
                            destroys[i] = new DestroyableComponentData()
                            {
                                ShouldDestroy = true
                            };
                            foreach (var velocitiesChunk in velocitiesChunks)
                            {
                                var teamTags          = velocitiesChunk.GetNativeArray(typeTeamTag);
                                var physicsVelocities = velocitiesChunk.GetNativeArray(typePhysicsVelocity);
                                for (var j = 0; j < teamTags.Length; j++)
                                {
                                    if (teamTags[j].Id != moveCommands[i].Id)
                                    {
                                        continue;
                                    }
                                    UnsafeUtilityEx
                                    .ArrayElementAsRef <PhysicsVelocity>(NativeArrayUnsafeUtility.GetUnsafeBufferPointerWithoutChecks(physicsVelocities), j)
                                    .Linear += moveCommands[i].DeltaVelocity;
                                }
                            }
                        }
                    }
                }
        }
        public static void PoisonUnusedChunkData(Chunk *chunk, byte value)
        {
            var   arch       = chunk->Archetype;
            int   bufferSize = Chunk.GetChunkBufferSize(arch->NumSharedComponents);
            byte *buffer     = chunk->Buffer;
            int   count      = chunk->Count;

            for (int i = 0; i < arch->TypesCount - 1; ++i)
            {
                int startOffset = arch->Offsets[i] + count * arch->SizeOfs[i];
                int endOffset   = arch->Offsets[i + 1];
                UnsafeUtilityEx.MemSet(buffer + startOffset, value, endOffset - startOffset);
            }
            int lastStartOffset = arch->Offsets[arch->TypesCount - 1] + count * arch->SizeOfs[arch->TypesCount - 1];

            UnsafeUtilityEx.MemSet(buffer + lastStartOffset, value, bufferSize - lastStartOffset);
        }
        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            var random          = new Unity.Mathematics.Random(RandomSeed);
            var index           = chunk.GetSharedComponentIndex(SpriteAnimationChunkType);
            var spriteAnimation = UniqueSpriteAnimations[index];
            var entities        = chunk.GetNativeArray(EntityChunkType);
            var states          = chunk.GetNativeArray(SpriteAnimationStateChunkType).GetUnsafePtr();
            var randomizers     = chunk.GetNativeArray(SpriteAnimationRandomizerChunkType);

            for (var i = 0; i < chunk.Count; ++i)
            {
                spriteAnimation.ClipIndex = random.NextInt(0, spriteAnimation.ClipCount);
                SpriteAnimationMap.TryAdd(entities[i], spriteAnimation);
                UnsafeUtilityEx.ArrayElementAsRef <SpriteAnimationState>(states, i).Speed =
                    random.NextFloat(randomizers[i].RandomSpeedStart, randomizers[i].RandomSpeedEnd);
            }
        }
        unsafe public void TestSphereColliderCreate()
        {
            var sphere = new SphereGeometry
            {
                Center = new float3(-8.45f, 9.65f, -0.10f),
                Radius = 0.98f
            };

            var collider       = SphereCollider.Create(sphere);
            var sphereCollider = UnsafeUtilityEx.AsRef <SphereCollider>(collider.GetUnsafePtr());

            TestUtils.AreEqual(sphere.Center, sphereCollider.Center, 1e-3f);
            TestUtils.AreEqual(sphere.Center, sphereCollider.Geometry.Center, 1e-3f);
            TestUtils.AreEqual(sphere.Radius, sphereCollider.Radius, 1e-3f);
            TestUtils.AreEqual(sphere.Radius, sphereCollider.Geometry.Radius, 1e-3f);
            Assert.AreEqual(ColliderType.Sphere, sphereCollider.Type);
            Assert.AreEqual(CollisionType.Convex, sphereCollider.CollisionType);
        }
        protected override unsafe void Build(void *dataPtr, BlobBuilder _, ITreeNode <INodeDataBuilder>[] __)
        {
            switch (Source)
            {
            case VelocitySource.Component:
                return;

            case VelocitySource.CustomGlobal:
                UnsafeUtilityEx.AsRef <CharacterSimpleMoveWithCustomGlobalVelocityNode>(dataPtr).Velocity = CustomVelocity;
                break;

            case VelocitySource.CustomLocal:
                UnsafeUtilityEx.AsRef <CharacterSimpleMoveWithCustomLocalVelocityNode>(dataPtr).Velocity = CustomVelocity;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
        public static void PoisonUnusedChunkData(Chunk *chunk, byte value)
        {
            var arch       = chunk->Archetype;
            var bufferSize = Chunk.GetChunkBufferSize(arch->TypesCount, arch->NumSharedComponents);
            var buffer     = chunk->Buffer;
            var count      = chunk->Count;

            for (int i = 0; i < arch->TypesCount - 1; ++i)
            {
                var index       = arch->TypeMemoryOrder[i];
                var nextIndex   = arch->TypeMemoryOrder[i + 1];
                var startOffset = arch->Offsets[index] + count * arch->SizeOfs[index];
                var endOffset   = arch->Offsets[nextIndex];
                UnsafeUtilityEx.MemSet(buffer + startOffset, value, endOffset - startOffset);
            }
            var lastIndex       = arch->TypeMemoryOrder[arch->TypesCount - 1];
            var lastStartOffset = arch->Offsets[lastIndex] + count * arch->SizeOfs[lastIndex];

            UnsafeUtilityEx.MemSet(buffer + lastStartOffset, value, bufferSize - lastStartOffset);
        }