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(); }
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) } } }
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(); }
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)); }
int?AddAccessor <T>(BufferAccessor buffer) where T : struct { if (buffer == null) { return(default);
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; } } }
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(); }