Ejemplo n.º 1
0
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
            {
                //BufferAccessor<Cell> accessor = this.GridChunks[0].GetBufferAccessor(this.CellTypeRO);
                //DynamicBuffer<Cell> grid = accessor[0].Reinterpret<Cell>();


                int size = DimX * DimY;
                BufferAccessor <Waypoint>            Waypoints              = chunk.GetBufferAccessor(WaypointChunkBuffer);
                NativeArray <PathRequest>            PathRequests           = chunk.GetNativeArray(PathRequestsChunkComponent);
                NativeArray <Translation>            Translations           = chunk.GetNativeArray(TranslationsChunkComponent);
                NativeArray <NavigationCapabilities> NavigationCapabilities = chunk.GetNativeArray(NavigationCapabilitiesChunkComponent);

                NativeArray <float> CostSoFar = new NativeArray <float>(size * chunk.Count, Allocator.Temp);
                NativeArray <int2>  CameFrom  = new NativeArray <int2>(size * chunk.Count, Allocator.Temp);
                NativeMinHeap       OpenSet   = new NativeMinHeap((Iterations + 1) * Neighbors.Length * chunk.Count, Allocator.Temp);

                for (int i = chunkIndex; i < chunk.Count; i++)
                {
                    NativeSlice <float> costSoFar = CostSoFar.Slice(i * size, size);
                    NativeSlice <int2>  cameFrom  = CameFrom.Slice(i * size, size);

                    int           openSetSize = (Iterations + 1) * NeighborCount;
                    NativeMinHeap openSet     = OpenSet.Slice(i * openSetSize, openSetSize);
                    PathRequest   request     = PathRequests[i];

                    // Clear our shared data
                    //var buffer = costSoFar.GetUnsafePtr();
                    //UnsafeUtility.MemClear(buffer, (long)costSoFar.Length * UnsafeUtility.SizeOf<float>());
                    //openSet.Clear();

                    Translation            currentPosition = Translations[i];
                    NavigationCapabilities capability      = NavigationCapabilities[i];

                    // cache these as they're used a lot
                    int2 start = currentPosition.Value.xy.FloorToInt();
                    int2 goal  = request.end;



                    DynamicBuffer <float3> waypoints = Waypoints[i].Reinterpret <float3>();
                    waypoints.Clear();

                    // Special case when the start is the same point as the goal
                    if (start.Equals(goal))
                    {
                        // We just set the destination as the goal, but need to get the correct height
                        int    gridIndex = this.GetIndex(goal);
                        Cell   cell      = CellArray[gridIndex];
                        float3 point     = new float3(request.Destination.x, request.Destination.y, cell.Height);
                        waypoints.Add(point);
                        continue;
                    }

                    var stash = new InstanceStash
                    {
                        Grid            = CellArray,
                        CameFrom        = cameFrom,
                        CostSoFar       = costSoFar,
                        OpenSet         = openSet,
                        Request         = request,
                        Capability      = capability,
                        CurrentPosition = currentPosition,
                        Start           = start,
                        Goal            = goal,
                        Waypoints       = waypoints,
                    };

                    if (this.ProcessPath(ref stash))
                    {
                        this.ReconstructPath(stash);
                    }
                }
                CostSoFar.Dispose();
                CameFrom.Dispose();
                OpenSet.Dispose();
            }
Ejemplo n.º 2
0
        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            NativeArray <Entity> entityArray = chunk.GetNativeArray(entityType);
            NativeArray <HasReynoldsSeekTargetPos> reynoldsArray = chunk.GetNativeArray(reynoldsType);
            NativeArray <FollowWayPointsAction>    followWPArray = chunk.GetNativeArray(followWPType);
            NativeArray <Translation> transArray    = chunk.GetNativeArray(translationType);
            BufferAccessor <Action>   actionBuffers = chunk.GetBufferAccessor <Action>(actionBufferType);
            BufferAccessor <WayPoint> wpBuffers     = chunk.GetBufferAccessor <WayPoint>(wayPointBufferType);

            for (int i = 0; i < chunk.Count; i++)
            {
                Entity entity = entityArray[i];
                DynamicBuffer <Action>   actions   = actionBuffers[i];
                DynamicBuffer <WayPoint> wayPoints = wpBuffers[i];
                HasReynoldsSeekTargetPos seek      = reynoldsArray[i];
                FollowWayPointsAction    data      = followWPArray[i];
                Translation trans = transArray[i];


                if (actions.Length > 0)                                                                //if there are actions
                {
                    if (actions[0].id == data.id)                                                      //if the current action is the same as the action in the first position
                    {
                        if (math.distance(trans.Value, wayPoints[data.curPointNum].value) < tolerance) // if the entity is within tolerance of the waypoint
                        {
                            if (data.curPointNum < wayPoints.Length - 1)                               // if the entity has at least one more waypoint to follow
                            {
                                data.curPointNum++;                                                    // the index increases by one
                                seek.targetPos = wayPoints[data.curPointNum].value;                    // move to the next point
                            }
                            else                                                                       // if there are no more waypoints
                                   //entityCommandBuffer.DestroyEntity(actions[0].dataHolder);//demolish the storage entity
                            {
                                Debug.Log("Got to last point");
                                entityCommandBuffer.AddComponent <RemoveAction>(chunkIndex, entity, new RemoveAction { // add a component that tells the system to remove the action from the queue
                                    id = data.id
                                });
                                entityCommandBuffer.RemoveComponent <HasReynoldsSeekTargetPos>(chunkIndex, entity);
                                entityCommandBuffer.RemoveComponent <FollowWayPointsAction>(chunkIndex, entity);
                                //remove the current follow waypoints action
                            }
                        }
                    }
                    else  // if there are actions but this action is not the right one
                    {
                        Debug.Log("Gotta change!");
                        int j = 0;
                        while (j < actions.Length && actions[j].id != data.id) // find the location of the action in the actions queue
                        {
                            j++;
                        }
                        if (j < actions.Length)                                                                        // if the action was found in the queue
                        {
                            entityCommandBuffer.AddComponent <StoreWayPoints>(chunkIndex, entity, new StoreWayPoints { // store the data
                                id          = data.id,
                                dataHolder  = actions[j].dataHolder,
                                curPointNum = data.curPointNum
                            });
                        }
                        entityCommandBuffer.AddComponent <ChangeAction>(chunkIndex, entity, new ChangeAction {
                        });                                                                                      //signify that the action should be changed
                    }
                }
                else  // if there are no actions in the action queue
                {
                    Debug.Log("Nothin left!");
                    entityCommandBuffer.RemoveComponent <HasReynoldsSeekTargetPos>(chunkIndex, entity);
                    entityCommandBuffer.RemoveComponent <FollowWayPointsAction>(chunkIndex, entity);
                    entityCommandBuffer.AddComponent <ChangeAction>(chunkIndex, entity, new ChangeAction {
                    });                                                                                      //signify that the action should be changed (will remove action)
                }
            }
        }
Ejemplo n.º 3
0
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
            {
                //Writeable.
                NativeArray <PathFinding> pathfindingArray       = chunk.GetNativeArray(pathFindingComponentHandle);
                BufferAccessor <PathNode> pathNodeBufferAccessor = chunk.GetBufferAccessor(pathNodeBufferHandle);

                //Read Only.
                NativeArray <CurrentTarget> currentTargetArray = chunk.GetNativeArray(currentTargetComponentHandle);
                NativeArray <Translation>   translationArray   = chunk.GetNativeArray(translationComponentHandle);
                NativeArray <Entity>        entities           = chunk.GetNativeArray(entityType);

                //Create a copy of the grid for this thread and chunk.
                NativeArray2D <MapNode> gridCopy = new NativeArray2D <MapNode>(gridRef.Length0, gridRef.Length1, Allocator.Temp, NativeArrayOptions.UninitializedMemory);

                UnsafeUtility.MemCpy(gridCopy.GetUnsafePtr(), gridRef.GetUnsafePtrReadOnly(), gridRef.Length * sizeof(MapNode));

                for (int indexInChunk = 0; indexInChunk < chunk.Count; ++indexInChunk)
                {
                    //Writable.
                    PathFinding pathfinding       = pathfindingArray[indexInChunk];
                    DynamicBuffer <PathNode> path = pathNodeBufferAccessor[indexInChunk];

                    //Read Only.
                    Entity        entity        = entities[indexInChunk];
                    CurrentTarget currentTarget = currentTargetArray[indexInChunk];
                    Translation   translation   = translationArray[indexInChunk];

                    bool hasPath = chunk.Has(hasPathComponentHandle);

                    if (!pathfinding.requestedPath)
                    {
                        //We only want to remove our has path component if we didn't request a new one, to avoid re-adding later in the job if we find a new path.
                        if (pathfinding.completedPath)
                        {
                            pathfinding.completedPath = false;
                            ecb.RemoveComponent <HasPathTag>(chunkIndex, entity);
                            pathfindingArray[indexInChunk] = pathfinding;
                        }

                        continue;
                    }

                    path.Clear();
                    pathfinding.currentIndexOnPath = 0;
                    pathfinding.completedPath      = false;
                    pathfinding.requestedPath      = false;

                    //Calculate the closest nodes to us and our target position.
                    //Don't search for path if we're already at our target node.
                    pathfinding.currentNode = FindNearestNode(translation.Value, gridCopy);
                    pathfinding.targetNode  = FindNearestNode(currentTarget.targetData.targetPos, gridCopy);
                    if (pathfinding.targetNode.Equals(pathfinding.currentNode))
                    {
                        pathfindingArray[indexInChunk] = pathfinding;
                        continue;
                    }

                    CalculateGridH(gridCopy, ref pathfinding);

                    bool pathfound = SearchForPath(pathfinding.currentNode, pathfinding.targetNode, gridCopy);

                    if (pathfound)
                    {
                        ConstructPath(gridCopy, ref pathfinding, ref path);

                        if (!hasPath)
                        {
                            ecb.AddComponent <HasPathTag>(chunkIndex, entity);
                        }
                    }
                    else if (hasPath)
                    {
                        ecb.RemoveComponent <HasPathTag>(chunkIndex, entity);
                    }

                    pathfindingArray[indexInChunk] = pathfinding;
                }

                gridCopy.Dispose();
            }
Ejemplo n.º 4
0
        public static int AddAccessorTo(this BufferAccessor self,
                                        Vrm10Storage storage, int bufferIndex,
                                        // GltfBufferTargetType targetType,
                                        bool useSparse,
                                        Action <ArraySegment <byte>, glTFAccessor> minMax = null,
                                        int offset = 0, int count = 0)
        {
            if (self.ComponentType == AccessorValueType.FLOAT &&
                self.AccessorType == AccessorVectorType.VEC3
                )
            {
                var values = self.GetSpan <Vector3>();
                // 巨大ポリゴンのモデル対策にValueTupleの型をushort -> uint へ
                var sparseValuesWithIndex = new List <ValueTuple <int, Vector3> >();
                for (int i = 0; i < values.Length; ++i)
                {
                    var v = values[i];
                    if (v != Vector3.Zero)
                    {
                        sparseValuesWithIndex.Add((i, v));
                    }
                }

                //var status = $"{sparseIndices.Count * 14}/{values.Length * 12}";
                if (useSparse &&
                    sparseValuesWithIndex.Count > 0 && // avoid empty sparse
                    sparseValuesWithIndex.Count * 16 < values.Length * 12)
                {
                    // use sparse
                    var sparseIndexBin  = new ArraySegment <byte>(new byte[sparseValuesWithIndex.Count * 4]);
                    var sparseIndexSpan = SpanLike.Wrap <Int32>(sparseIndexBin);
                    var sparseValueBin  = new ArraySegment <byte>(new byte[sparseValuesWithIndex.Count * 12]);
                    var sparseValueSpan = SpanLike.Wrap <Vector3>(sparseValueBin);

                    for (int i = 0; i < sparseValuesWithIndex.Count; ++i)
                    {
                        var(index, value)  = sparseValuesWithIndex[i];
                        sparseIndexSpan[i] = index;
                        sparseValueSpan[i] = value;
                    }

                    var sparseIndexView = storage.AppendToBuffer(bufferIndex, sparseIndexBin, 4);
                    var sparseValueView = storage.AppendToBuffer(bufferIndex, sparseValueBin, 12);

                    var accessorIndex = storage.Gltf.accessors.Count;
                    var accessor      = new glTFAccessor
                    {
                        componentType = (glComponentType)self.ComponentType,
                        type          = self.AccessorType.ToString(),
                        count         = self.Count,
                        sparse        = new glTFSparse
                        {
                            count   = sparseValuesWithIndex.Count,
                            indices = new glTFSparseIndices
                            {
                                componentType = (glComponentType)AccessorValueType.UNSIGNED_INT,
                                bufferView    = sparseIndexView,
                            },
                            values = new glTFSparseValues
                            {
                                bufferView = sparseValueView,
                            },
                        }
                    };
                    if (minMax != null)
                    {
                        minMax(sparseValueBin, accessor);
                    }
                    storage.Gltf.accessors.Add(accessor);
                    return(accessorIndex);
                }
            }

            var viewIndex = self.AddViewTo(storage, bufferIndex, offset, count);

            return(self.AddAccessorTo(storage, viewIndex, minMax, 0, count));
        }
Ejemplo n.º 5
0
 int?AddAccessor <T>(BufferAccessor buffer) where T : struct
 {
     if (buffer == null)
     {
         return(default);
Ejemplo n.º 6
0
            public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
            {
                NativeArray <NavigationGridData>  navigationGrids    = chunk.GetNativeArray(this.navigationGridType);
                BufferAccessor <AStarNodeElement> nodeBufferAccessor = chunk.GetBufferAccessor(this.nodeBufferType);

                for (int ci = 0, cn = chunk.Count; ci < cn; ci++)
                {
                    NavigationGridData navigationGrid           = outNavigationGrid[0] = navigationGrids[ci];
                    DynamicBuffer <AStarNodeElement> nodeBuffer = nodeBufferAccessor[ci];

                    // Solve path if requested

                    if (navigationGrid.pathRequested)
                    {
                        // All nodes
                        NativeArray <AStarNode> nodes = nodeBuffer.Reinterpret <AStarNode>().ToNativeArray(Allocator.Temp);

                        // Create temp grid
                        AStarGrid aStarGrid = new AStarGrid(navigationGrid.lengthX, navigationGrid.lengthY, nodes);

                        // Start/end nodes
                        AStarNode start = navigationGrid.pathStart;
                        AStarNode end   = navigationGrid.pathEnd;

                        // Solve path
                        NativeList <AStarNode> pathNodeList = new NativeList <AStarNode>(Allocator.Temp);
                        bool pathFound  = AStarSolver.SolvePath(aStarGrid, start, end, ref pathNodeList);
                        int  pathLength = pathNodeList.Length;
                        if (pathFound && navigationGrid.pathMustBeStraightLine)
                        {
                            // Check if path is straight line if specfied as a requirement
                            bool xDiverge = false;
                            bool yDiverge = false;
                            for (int i = 1, n = pathNodeList.Length; i < n; i++)
                            {
                                if (!xDiverge)
                                {
                                    xDiverge = pathNodeList[i].XCoord != pathNodeList[i - 1].XCoord;
                                }
                                if (!yDiverge)
                                {
                                    yDiverge = pathNodeList[i].YCoord != pathNodeList[i - 1].YCoord;
                                }
                                if (xDiverge && yDiverge)
                                {
                                    pathFound = false;
                                    break;
                                }
                            }
                        }


                        // Copy path node list to output array
                        NativeSlice <AStarNode> pathNodeListSlice = new NativeSlice <AStarNode>(pathNodeList.AsArray());
                        NativeSlice <AStarNode> pathNodeSlice     = new NativeSlice <AStarNode>(this.outPathNodes, 0, pathLength);
                        pathNodeSlice.CopyFrom(pathNodeListSlice);

                        // Dispose native containers
                        pathNodeList.Dispose();
                        aStarGrid.Dispose();
                        nodes.Dispose();

                        this.outPathFound[0]                  = pathFound ? 1 : 0;
                        this.outPathFound[1]                  = pathLength;
                        navigationGrid.pathRequested          = false;
                        navigationGrid.pathMustBeStraightLine = false;

                        // Apply changes
                        navigationGrids[ci] = navigationGrid;
                    }
                }
            }
Ejemplo n.º 7
0
        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            GhostDeserializerState deserializerState = new GhostDeserializerState
            {
                GhostMap = GhostMap
            };
            NativeArray <Entity> ghostEntityArray = chunk.GetNativeArray(ghostEntityType);
            BufferAccessor <NetCodeTestGhostObjectSnapshotData> ghostSnapshotDataArray =
                chunk.GetBufferAccessor(ghostSnapshotDataType);
            NativeArray <PredictedGhostComponent> predictedGhostComponentArray =
                chunk.GetNativeArray(predictedGhostComponentType);
            NativeArray <Rotation>    ghostRotationArray    = chunk.GetNativeArray(ghostRotationType);
            NativeArray <Translation> ghostTranslationArray = chunk.GetNativeArray(ghostTranslationType);

#if UNITY_EDITOR || DEVELOPMENT_BUILD
            int minMaxOffset = ThreadIndex * (JobsUtility.CacheLineSize / 4);
#endif
            for (int entityIndex = 0; entityIndex < ghostEntityArray.Length; ++entityIndex)
            {
                DynamicBuffer <NetCodeTestGhostObjectSnapshotData> snapshot = ghostSnapshotDataArray[entityIndex];
#if UNITY_EDITOR || DEVELOPMENT_BUILD
                uint latestTick = snapshot.GetLatestTick();
                if (latestTick != 0)
                {
                    if (minMaxSnapshotTick[minMaxOffset] == 0 ||
                        SequenceHelpers.IsNewer(minMaxSnapshotTick[minMaxOffset], latestTick))
                    {
                        minMaxSnapshotTick[minMaxOffset] = latestTick;
                    }

                    if (minMaxSnapshotTick[minMaxOffset + 1] == 0 ||
                        SequenceHelpers.IsNewer(latestTick, minMaxSnapshotTick[minMaxOffset + 1]))
                    {
                        minMaxSnapshotTick[minMaxOffset + 1] = latestTick;
                    }
                }
#endif
                NetCodeTestGhostObjectSnapshotData snapshotData;
                snapshot.GetDataAtTick(targetTick, out snapshotData);

                PredictedGhostComponent predictedData = predictedGhostComponentArray[entityIndex];
                uint lastPredictedTickInst            = lastPredictedTick;
                if (lastPredictedTickInst == 0 || predictedData.AppliedTick != snapshotData.Tick)
                {
                    lastPredictedTickInst = snapshotData.Tick;
                }
                else if (!SequenceHelpers.IsNewer(lastPredictedTickInst, snapshotData.Tick))
                {
                    lastPredictedTickInst = snapshotData.Tick;
                }

                if (minPredictedTick[ThreadIndex] == 0 ||
                    SequenceHelpers.IsNewer(minPredictedTick[ThreadIndex], lastPredictedTickInst))
                {
                    minPredictedTick[ThreadIndex] = lastPredictedTickInst;
                }

                predictedGhostComponentArray[entityIndex] = new PredictedGhostComponent
                {
                    AppliedTick = snapshotData.Tick, PredictionStartTick = lastPredictedTickInst
                };
                if (lastPredictedTickInst != snapshotData.Tick)
                {
                    continue;
                }

                Rotation    ghostRotation    = ghostRotationArray[entityIndex];
                Translation ghostTranslation = ghostTranslationArray[entityIndex];
                ghostRotation.Value                = snapshotData.GetRotationValue(deserializerState);
                ghostTranslation.Value             = snapshotData.GetTranslationValue(deserializerState);
                ghostRotationArray[entityIndex]    = ghostRotation;
                ghostTranslationArray[entityIndex] = ghostTranslation;
            }
        }
        public unsafe void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            float3 up = math.up();

            var chunkCCData              = chunk.GetNativeArray(CharacterControllerComponentType);
            var chunkCCInternalData      = chunk.GetNativeArray(CharacterControllerInternalType);
            var chunkPhysicsColliderData = chunk.GetNativeArray(PhysicsColliderType);
            var chunkTranslationData     = chunk.GetNativeArray(TranslationType);
            var chunkRotationData        = chunk.GetNativeArray(RotationType);

            var hasChunkCollisionEventBufferType = chunk.Has(CollisionEventBufferType);
            var hasChunkTriggerEventBufferType   = chunk.Has(TriggerEventBufferType);

            BufferAccessor <StatefulCollisionEvent> collisionEventBuffers = default;
            BufferAccessor <StatefulTriggerEvent>   triggerEventBuffers   = default;

            if (hasChunkCollisionEventBufferType)
            {
                collisionEventBuffers = chunk.GetBufferAccessor(CollisionEventBufferType);
            }
            if (hasChunkTriggerEventBufferType)
            {
                triggerEventBuffers = chunk.GetBufferAccessor(TriggerEventBufferType);
            }

            DeferredImpulseWriter.BeginForEachIndex(chunkIndex);

            for (int i = 0; i < chunk.Count; i++)
            {
                var ccComponentData = chunkCCData[i];
                var ccInternalData  = chunkCCInternalData[i];
                var collider        = chunkPhysicsColliderData[i];
                var position        = chunkTranslationData[i];
                var rotation        = chunkRotationData[i];
                DynamicBuffer <StatefulCollisionEvent> collisionEventBuffer = default;
                DynamicBuffer <StatefulTriggerEvent>   triggerEventBuffer   = default;

                if (hasChunkCollisionEventBufferType)
                {
                    collisionEventBuffer = collisionEventBuffers[i];
                }

                if (hasChunkTriggerEventBufferType)
                {
                    triggerEventBuffer = triggerEventBuffers[i];
                }

                // Collision filter must be valid
                if (!collider.IsValid || collider.Value.Value.Filter.IsEmpty)
                {
                    continue;
                }

                // Character step input
                CharacterControllerStepInput stepInput = new CharacterControllerStepInput
                {
                    World            = PhysicsWorld,
                    DeltaTime        = DeltaTime,
                    Up               = math.up(),
                    Gravity          = ccComponentData.Gravity,
                    MaxIterations    = ccComponentData.MaxIterations,
                    Tau              = k_DefaultTau,
                    Damping          = k_DefaultDamping,
                    SkinWidth        = ccComponentData.SkinWidth,
                    ContactTolerance = ccComponentData.ContactTolerance,
                    MaxSlope         = ccComponentData.MaxSlope,
                    RigidBodyIndex   = PhysicsWorld.GetRigidBodyIndex(ccInternalData.Entity),
                    CurrentVelocity  = ccInternalData.LinearVelocity,
                    MaxMovementSpeed = ccComponentData.MaxMovementSpeed
                };

                // Character transform
                RigidTransform transform = new RigidTransform
                {
                    pos = position.Value,
                    rot = rotation.Value
                };

                NativeList <StatefulCollisionEvent> currentFrameCollisionEvents = default;
                NativeList <StatefulTriggerEvent>   currentFrameTriggerEvents   = default;

                if (ccComponentData.RaiseCollisionEvents != 0)
                {
                    currentFrameCollisionEvents = new NativeList <StatefulCollisionEvent>(Allocator.Temp);
                }

                if (ccComponentData.RaiseTriggerEvents != 0)
                {
                    currentFrameTriggerEvents = new NativeList <StatefulTriggerEvent>(Allocator.Temp);
                }


                // Check support
                CheckSupport(ref PhysicsWorld, ref collider, stepInput, transform,
                             out ccInternalData.SupportedState, out float3 surfaceNormal, out float3 surfaceVelocity,
                             currentFrameCollisionEvents);

                // User input
                float3 desiredVelocity = ccInternalData.LinearVelocity;
                HandleUserInput(ccComponentData, stepInput.Up, surfaceVelocity, ref ccInternalData, ref desiredVelocity);

                // Calculate actual velocity with respect to surface
                if (ccInternalData.SupportedState == CharacterSupportState.Supported)
                {
                    CalculateMovement(ccInternalData.CurrentRotationAngle, stepInput.Up, ccInternalData.IsJumping,
                                      ccInternalData.LinearVelocity, desiredVelocity, surfaceNormal, surfaceVelocity, out ccInternalData.LinearVelocity);
                }
                else
                {
                    ccInternalData.LinearVelocity = desiredVelocity;
                }

                // World collision + integrate
                CollideAndIntegrate(stepInput, ccComponentData.CharacterMass, ccComponentData.AffectsPhysicsBodies != 0,
                                    collider.ColliderPtr, ref transform, ref ccInternalData.LinearVelocity, ref DeferredImpulseWriter,
                                    currentFrameCollisionEvents, currentFrameTriggerEvents);

                // Update collision event status
                if (currentFrameCollisionEvents.IsCreated)
                {
                    UpdateCollisionEvents(currentFrameCollisionEvents, collisionEventBuffer);
                }

                if (currentFrameTriggerEvents.IsCreated)
                {
                    UpdateTriggerEvents(currentFrameTriggerEvents, triggerEventBuffer);
                }

                // Write back and orientation integration
                position.Value = transform.pos;
                rotation.Value = quaternion.AxisAngle(up, ccInternalData.CurrentRotationAngle);

                // Write back to chunk data
                {
                    chunkCCInternalData[i]  = ccInternalData;
                    chunkTranslationData[i] = position;
                    chunkRotationData[i]    = rotation;
                }
            }

            DeferredImpulseWriter.EndForEachIndex();
        }