protected override void OnCreate() { var pointerArray = new NavMeshQueryPointer[JobsUtility.MaxJobThreadCount]; for (int i = 0; i < JobsUtility.MaxJobThreadCount; ++i) { pointerArray[i] = new NavMeshQueryPointer { Value = UnsafeUtility.Malloc( UnsafeUtility.SizeOf <NavMeshQuery>(), UnsafeUtility.AlignOf <NavMeshQuery>(), Allocator.Persistent ) }; var query = new NavMeshQuery( NavMeshWorld.GetDefaultWorld(), Allocator.Persistent, NavConstants.PATH_NODE_MAX ); queryList.Add(query); UnsafeUtility.CopyStructureToPtr(ref query, pointerArray[i].Value); } PointerArray = new NativeArray <NavMeshQueryPointer>(pointerArray, Allocator.Persistent); }
public void TryFindPath(Vector3 start, Vector3 end) { using (var polygonIds = new NativeArray <PolygonId>(100, Allocator.Persistent)) using (var query = new NavMeshQuery(NavMeshWorld.GetDefaultWorld(), Allocator.Persistent, 100)) { int maxIterations = 1024; var from = query.MapLocation(start, Vector3.one * 10, 0); var to = query.MapLocation(end, Vector3.one * 10, 0); var status = query.BeginFindPath(from, to); status = query.UpdateFindPath(maxIterations, out int currentIterations); var finalStatus = query.EndFindPath(out int pathLength); var pathResult = query.GetPathResult(polygonIds); var straightPath = new NativeArray <NavMeshLocation>(pathLength, Allocator.Temp); paths = new Vector3[pathResult]; for (int i = 0; i < pathResult; i++) { var polyId = polygonIds[i]; var polyWorldToLocal = query.PolygonWorldToLocalMatrix(polyId); var b = query.CreateLocation(paths[i], polyId); paths[i] = b.position; //Debug.Log(b.position); } //Debug.Log(pathResult); Debug.DrawLine(from.position, to.position); } }
IEnumerator StartQuery() { NavMeshWorld world = NavMeshWorld.GetDefaultWorld(); NavMeshQuery query = new NavMeshQuery(world, Allocator.Persistent, maxPath); NavMeshLocation startLocation = query.MapLocation(start.position, Vector3.up * extents, 0); NavMeshLocation endLocation = query.MapLocation(end.position, Vector3.up * extents, 0); PathQueryStatus status = query.BeginFindPath(startLocation, endLocation); yield return(new WaitWhile(() => { status = query.UpdateFindPath(8, out int iterationsPerformed); return status == PathQueryStatus.InProgress; })); status = query.EndFindPath(out int pathsize); NativeArray <PolygonId> path = new NativeArray <PolygonId>(pathsize, Allocator.Temp); int pathResult = query.GetPathResult(path); //NativeArray<NavMeshLocation> pathStraight = new NativeArray<NavMeshLocation>(maxPath, Allocator.Temp); ////NativeArray<StraightPathFlag> pathStreaigthFlag = new NativeArray<StraightPathFlags>(maxPath, Allocator.Temp); //NativeArray<float> vertexSize = new NativeArray<float>(maxPath, Allocator.Temp); // //int straghtPathCount = 0; for (var i = 0; i < pathResult; i++) { var p = path[i]; var loc = query.CreateLocation(start.position, p); var target = loc.position; } query.Dispose(); }
protected override void OnCreate() { var settings = pathSystem.Settings; var pointerArray = new PathMeshQueryPointer[JobsUtility.MaxJobThreadCount]; for (var i = 0; i < JobsUtility.MaxJobThreadCount; ++i) { pointerArray[i] = new PathMeshQueryPointer { Value = UnsafeUtility.Malloc( UnsafeUtility.SizeOf <NavMeshQuery>(), UnsafeUtility.AlignOf <NavMeshQuery>(), Allocator.Persistent ) }; var query = new NavMeshQuery( NavMeshWorld.GetDefaultWorld(), Allocator.Persistent, settings.PathMeshQueryNodeMax ); queryList.Add(query); UnsafeUtility.CopyStructureToPtr(ref query, pointerArray[i].Value); } PointerArray = new NativeArray <PathMeshQueryPointer>(pointerArray, Allocator.Persistent); }
protected override void OnCreateManager(int capacity) { var world = NavMeshWorld.GetDefaultWorld(); query = new NavMeshQuery(world, Allocator.Persistent); agentType = NavMesh.GetSettingsByIndex(1).agentTypeID; }
public PathQueryQueueEcs(int nodePoolSize, int maxRequestCount) { var world = NavMeshWorld.GetDefaultWorld(); m_Query = new NavMeshQuery(world, Allocator.Persistent, nodePoolSize); m_Requests = new NativeArray <RequestEcs>(maxRequestCount, Allocator.Persistent); m_ResultNodes = new NativeArray <PolygonId>(2 * nodePoolSize, Allocator.Persistent); m_ResultRanges = new NativeArray <PathInfo>(maxRequestCount + 1, Allocator.Persistent); m_AgentIndices = new NativeArray <int>(maxRequestCount + 1, Allocator.Persistent); m_Costs = new NativeArray <float>(32, Allocator.Persistent); for (var i = 0; i < m_Costs.Length; ++i) { m_Costs[i] = 1.0f; } m_State = new NativeArray <QueryQueueState>(1, Allocator.Persistent); m_State[0] = new QueryQueueState() { requestCount = 0, requestIndex = 0, resultNodesCount = 0, resultPathsCount = 0, currentAgentIndex = -1, currentPathRequest = new PathInfo() }; }
public void Awake() { Instance = this; // worst singleton ever but it works entityManager = World.Active.GetExistingManager <EntityManager>(); var navMeshWorld = NavMeshWorld.GetDefaultWorld(); mapLocationQuery = new NavMeshQuery(navMeshWorld, Allocator.Persistent); }
protected override void OnCreate() { AgentsGroup = GetEntityQuery(typeof(NavAgent), ComponentType.ReadWrite <Translation>(), ComponentType.ReadWrite <Rotation>(), ComponentType.ReadWrite <LocalToWorld>()); var navMeshWorld = NavMeshWorld.GetDefaultWorld(); NavMeshQuery = new NavMeshQuery(navMeshWorld, Allocator.Persistent, 100); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { var lookup = GetBufferFromEntity <PathBufferElement>(); var commandBuffer = commandBufferSystem.CreateCommandBuffer().ToConcurrent(); var world = NavMeshWorld.GetDefaultWorld(); var pathfindingDatas = requests.ToComponentDataArray <NavMeshPathfindingRequestData>(Allocator.TempJob); var entities = requests.ToEntityArray(Allocator.TempJob); var jobs = new NativeArray <JobHandle>(pathfindingDatas.Length, Allocator.TempJob); JobHandle jobHandle = inputDeps; for (var i = 0; i < entities.Length; ++i) { var entity = entities[i]; //Destroy finished requests if (pathfindingDatas[i].Status == PathSearchStatus.Finished) { navMeshQueries[entity].Dispose(); navMeshQueries.Remove(entity); EntityManager.DestroyEntity(entity); continue; } //Process requests in progress if (!navMeshQueries.TryGetValue(entity, out var query)) { query = navMeshQueries[entity] = new NavMeshQuery(world, Allocator.Persistent, MAXIMUM_POOL_SIZE); } var navMeshPathfindingJob = new NavMeshPathfindingJob { BuffersLookup = lookup, CommandBuffer = commandBuffer, JobIndex = i, Request = pathfindingDatas[i], Query = query, MaximumPoolSize = MAXIMUM_POOL_SIZE, EntityRequestId = entity }; jobs[i] = navMeshPathfindingJob.Schedule(inputDeps); } jobHandle = JobHandle.CombineDependencies(jobs); pathfindingDatas.Dispose(); entities.Dispose(); jobs.Dispose(); commandBufferSystem.AddJobHandleForProducer(jobHandle); return(jobHandle); }
protected override void OnCreate() { base.OnCreate(); var navWorld = NavMeshWorld.GetDefaultWorld(); agentQuery = GetEntityQuery(new EntityQueryDesc { All = new ComponentType[] { ComponentType.ReadWrite <AgentComponent>(), ComponentType.ReadWrite <LocalToWorld>() }, }); }
private void Reconfigure() { foreach (var query in idleQueries) { query.Dispose(); } idleQueries = new Queue <NavMeshQuery>( Enumerable.Range(0, maxNumParallelQueries) .Select(x => new NavMeshQuery(NavMeshWorld.GetDefaultWorld(), Allocator.Persistent, PathNodePoolSizeDefault))); }
protected override void OnCreate() { var agentQueryDesc = new EntityQueryDesc { All = new ComponentType[] { typeof(NavAgent), typeof(NavAgentAvoidance) } }; _agentQuery = GetEntityQuery(agentQueryDesc); _navMeshQuery = new NavMeshQuery(NavMeshWorld.GetDefaultWorld(), Allocator.Persistent, 128); IndexMap = new NativeMultiHashMap <int, int>(100 * 1024, Allocator.Persistent); NextPositionMap = new NativeMultiHashMap <int, float3>(100 * 1024, Allocator.Persistent); _querySystem = World.GetOrCreateSystem <NavMeshQuerySystem>(); }
public RequestBatch(int nodePoolSize = 2000) { var world = NavMeshWorld.GetDefaultWorld(); query = new NavMeshQuery(world, Allocator.Persistent, nodePoolSize); entities = new NativeArray <Entity>(MAX_COUNT, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); requests = new NativeArray <PathRequestData>(MAX_COUNT, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); pathBuffer = new NativeArray <PathPoint>(MAX_COUNT * MAX_PATHSIZE, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); pathStart = new NativeArray <int>(MAX_COUNT, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); state = new NativeArray <State>(1, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); resultBuffer = new NativeArray <PolygonId>(MAX_COUNT * 5, Allocator.Persistent, NativeArrayOptions.UninitializedMemory); var s = new State(); s.entityInUse = State.NONE; s.entitySize = 0; s.pathSize = 0; state[0] = s; }
void Initialize(int capacity) { var world = NavMeshWorld.GetDefaultWorld(); var queryCount = world.IsValid() ? k_QueryCount : 0; var agentCount = world.IsValid() ? capacity : 0; m_PlanPathForAgent = new NativeList <bool1>(agentCount, Allocator.Persistent); m_EmptyPlanPathForAgent = new NativeList <bool1>(0, Allocator.Persistent); m_PathRequestIdForAgent = new NativeList <uint>(agentCount, Allocator.Persistent); m_PathRequests = new NativeList <PathQueryQueueEcs.RequestEcs>(k_PathRequestsPerTick, Allocator.Persistent); m_PathRequests.ResizeUninitialized(k_PathRequestsPerTick); for (var i = 0; i < m_PathRequests.Length; i++) { m_PathRequests[i] = new PathQueryQueueEcs.RequestEcs { uid = PathQueryQueueEcs.RequestEcs.invalidId }; } m_PathRequestsRange = new NativeArray <int>(k_DataSize, Allocator.Persistent); m_PathRequestsRange[k_Start] = 0; m_PathRequestsRange[k_Count] = 0; m_UniqueIdStore = new NativeArray <uint>(1, Allocator.Persistent); m_CurrentAgentIndex = new NativeArray <int>(1, Allocator.Persistent); m_CurrentAgentIndex[0] = 0; m_NavMeshQuery = new NavMeshQuery(world, Allocator.Persistent); m_QueryQueues = new PathQueryQueueEcs[queryCount]; m_QueryJobs = new UpdateQueriesJob[queryCount]; m_AfterQueriesProcessed = new NativeArray <JobHandle>(queryCount, Allocator.Persistent); m_AfterQueriesCleanup = new JobHandle(); m_AfterMovedRequestsForgotten = new JobHandle(); m_IsEmptyQueryQueue = new bool[queryCount]; for (var i = 0; i < m_QueryQueues.Length; i++) { m_QueryQueues[i] = new PathQueryQueueEcs(k_MaxQueryNodes, k_MaxRequestsPerQuery); m_QueryJobs[i] = new UpdateQueriesJob() { maxIterations = k_MaxQueryIterationsPerTick, queryQueue = m_QueryQueues[i] }; m_AfterQueriesProcessed[i] = new JobHandle(); m_IsEmptyQueryQueue[i] = true; } }
protected override void OnCreate() { extents = new float3(10, 10, 10); allPaths = new Dictionary <int, float3[]>(); statusOutputs = new List <NativeArray <int> >(); results = new List <NativeArray <float3> >(); routedEntities = new List <Entity>(); queries = new List <NavMeshQuery>(); jobHandles = new List <JobHandle>(); for (int n = 0; n <= 32; n++) { NativeArray <float3> result = new NativeArray <float3>(1024, Allocator.Persistent); NativeArray <int> statusOutput = new NativeArray <int>(3, Allocator.Persistent); statusOutputs.Add(statusOutput); results.Add(result); } navMeshWorld = NavMeshWorld.GetDefaultWorld(); }
//---------------------- Collision Avoidance --------------------------- protected override void OnCreate() { Dictionary <string, string> configValues = Utils.GetConfigValues(); probabilityOfInfectionWithMaskWait = float.Parse(configValues["PROBABILITY_OF_INFECTION_WITH_MASK_WAIT"]) * 100; probabilityOfInfectionWait = float.Parse(configValues["PROBABILITY_OF_INFECTION_WAIT"]) * 100; probabilityOfInfectionWithMask = float.Parse(configValues["PROBABILITY_OF_INFECTION_WITH_MASK"]) * 100; probabilityOfInfection = float.Parse(configValues["PROBABILITY_OF_INFECTION"]) * 100; infectionDistance = float.Parse(configValues["INFECTION_DISTANCE"]); infectionDistanceWait = float.Parse(configValues["INFECTION_DISTANCE_WAIT"]); bi_ECB = World.GetOrCreateSystem <BeginInitializationEntityCommandBufferSystem>(); extents = new float3(100, 100, 100); allPaths = new Dictionary <string, float3[]>(); statusOutputs = new List <NativeArray <int> >(); results = new List <NativeArray <float3> >(); routedEntities = new List <Entity>(); queries = new List <NavMeshQuery>(); jobHandles = new List <JobHandle>(); keys = new List <string>(); totalNumberOfCovidExit = 0; totalNumberOfStudentsExit = 0; frameCounter = 0; for (int n = 0; n <= 4000; n++) //limit number equals to Max Entities routed per frame of UnitManager game object { NativeArray <float3> result = new NativeArray <float3>(1024, Allocator.Persistent); NativeArray <int> statusOutput = new NativeArray <int>(2, Allocator.Persistent); statusOutputs.Add(statusOutput); results.Add(result); keys.Add(""); } navMeshWorld = NavMeshWorld.GetDefaultWorld(); //---------------------- Collision Avoidance --------------------------- cellVsEntityPositions = new NativeMultiHashMap <int, CovidPos>(0, Allocator.Persistent); //---------------------- Collision Avoidance --------------------------- }
protected override void OnCreateManager(int capacity) { base.OnCreateManager(capacity); //costs = new NativeArray<float>(32, Allocator.Persistent); //for (int i = 0; i < 32; i++) costs[i] = 1; newPathQueries = new NativeQueue <Entity>(Allocator.Persistent); completePathQueries = new NativeQueue <Entity>(Allocator.Persistent); var navMeshWorld = NavMeshWorld.GetDefaultWorld(); queries = new NavMeshQuery[MaxNavMeshQueries]; queryIndexUsed = new NativeList <int>(MaxNavMeshQueries, Allocator.Persistent); queryIndexFree = new NativeList <int>(MaxNavMeshQueries, Allocator.Persistent); for (var i = 0; i < MaxNavMeshQueries; ++i) { queries[i] = new NavMeshQuery(navMeshWorld, Allocator.Persistent, MaxNavMeshNodes); queryIndexFree.Add(i); } findingEntities = new NativeList <Entity>(MaxNavMeshQueries, Allocator.Persistent); }
protected override void OnCreate() { world = NavMeshWorld.GetDefaultWorld(); locationQuery = new NavMeshQuery(world, Allocator.Persistent); availableSlots = new ConcurrentQueue <int>(); ProgressQueue = new NativeList <PathQueryData>(MaxQueries, Allocator.Persistent); handles = new List <JobHandle>(MaxQueries); takenSlots = new List <int>(MaxQueries); statuses = new List <NativeArray <int> >(MaxQueries); results = new List <NativeArray <NavMeshLocation> >(MaxQueries); jobs = new Dictionary <int, UpdateQueryStatusJob>(MaxQueries); queries = new NavMeshQuery[MaxQueries]; queryDatas = new PathQueryData[MaxQueries]; for (int i = 0; i < MaxQueries; i++) { handles.Add(new JobHandle()); statuses.Add(new NativeArray <int>(3, Allocator.Persistent)); results.Add(new NativeArray <NavMeshLocation>(MaxPathSize, Allocator.Persistent)); availableSlots.Enqueue(i); } QueryQueue = new ConcurrentQueue <PathQueryData>(); }
protected override void OnUpdate() { var allQueriesIdle = activeJobs.Length == 0; if (reconfigurationPending && allQueriesIdle) { Reconfigure(); reconfigurationPending = false; } var newActiveJobs = new List <UpdateNavMeshQueryJob>(); Entities.ForEach((Entity entity, ref QueryPathRequestData request) => { if (idleQueries.Any()) { newActiveJobs.Add(new UpdateNavMeshQueryJob() { navMeshQuery = idleQueries.Dequeue(), queryPathRequest = request, queryingEntity = entity, isFirstUpdate = true, numIterationsPerUpdate = MaxIterationsPerUpdateDefault, areaCosts = MakeAreaCosts(request.areaCostIndex), updateResult = new NativeArray <UpdateNavMeshQueryJob.UpdateResult>(1, Allocator.Persistent), pathResult = new NativeArray <float3>(MaxPathLength, Allocator.Persistent) }); PostUpdateCommands.RemoveComponent <QueryPathRequestData>(entity); } }); activeJobs = activeJobs.Concat(newActiveJobs).ToArray(); var activeJobHandles = activeJobs.Select(x => x.Schedule()).ToArray(); // wait for the jobs to finish using (var handles = new NativeArray <JobHandle>(activeJobHandles, Allocator.Temp)) { var combinedJobs = JobHandle.CombineDependencies(handles); NavMeshWorld.GetDefaultWorld().AddDependency(combinedJobs); combinedJobs.Complete(); } var jobsToContinue = new List <int>(); for (var activeJobIdx = 0; activeJobIdx < activeJobs.Length; ++activeJobIdx) { var updateResult = activeJobs[activeJobIdx].updateResult[0]; if (updateResult.queryStatus != PathQueryStatus.InProgress) { if ((updateResult.queryStatus == PathQueryStatus.Success) || (updateResult.queryStatus == PathQueryStatus.PartialResult)) { var buffer = PostUpdateCommands.AddBuffer <PathVertexResultData>(activeJobs[activeJobIdx].queryingEntity); buffer.ResizeUninitialized(updateResult.pathResultLength); for (int resultVertexIndex = 0; resultVertexIndex < updateResult.pathResultLength; resultVertexIndex++) { buffer[resultVertexIndex] = activeJobs[activeJobIdx].pathResult[resultVertexIndex]; } } if (activeJobs[activeJobIdx].areaCosts.IsCreated) { activeJobs[activeJobIdx].areaCosts.Dispose(); } if (activeJobs[activeJobIdx].pathResult.IsCreated) { activeJobs[activeJobIdx].pathResult.Dispose(); } if (activeJobs[activeJobIdx].updateResult.IsCreated) { activeJobs[activeJobIdx].updateResult.Dispose(); } idleQueries.Enqueue(activeJobs[activeJobIdx].navMeshQuery); } else { activeJobs[activeJobIdx].isFirstUpdate = false; jobsToContinue.Add(activeJobIdx); } } activeJobs = jobsToContinue.Select(x => activeJobs[x]).ToArray(); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { if (formations.Length == 0) { return(inputDeps); } var assign = new AssignFormationSpeed { navigators = formations.navigators, integrityData = formations.integrityData, formations = formations.data }; Profiler.BeginSample("Alloc"); var pathFollow = new MinionFollowPath { entities = minions.entities, newPathQueries = newPathQueries, pathsInfo = minions.pathsInfo, minionPaths = minions.paths, minionTargets = minions.targets, navMeshLocation = minions.navMeshLocation, maxPathSize = SimulationState.MaxPathSize }; Entity rmEnt; while (completePathQueries.TryDequeue(out rmEnt)) { // TODO: avoid linear search for (int i = 0; i < findingEntities.Length; ++i) { if (findingEntities[i] == rmEnt) { findingEntities.RemoveAtSwapBack(i); queryIndexFree.Add(queryIndexUsed[i]); queryIndexUsed.RemoveAtSwapBack(i); break; } } } for (int i = 0; i < findingEntities.Length; ++i) { if (!entityManager.Exists(findingEntities[i])) { findingEntities.RemoveAtSwapBack(i); queryIndexFree.Add(queryIndexUsed[i]); queryIndexUsed.RemoveAtSwapBack(i); --i; } } // Refill with new path queries while (findingEntities.Length < MaxNavMeshQueries && newPathQueries.Count > 0) { // TODO: should use some kind of round robin to make sure all minions get a chance to path find findingEntities.Add(newPathQueries.Dequeue()); queryIndexUsed.Add(queryIndexFree[queryIndexFree.Length - 1]); queryIndexFree.RemoveAtSwapBack(queryIndexFree.Length - 1); } //Debug.Assert(queryIndexFree.Length + queryIndexUsed.Length == MaxNavMeshQueries); var navMeshWorld = NavMeshWorld.GetDefaultWorld(); newPathQueries.Clear(); var findHandle = inputDeps; for (int i = 0; i < findingEntities.Length; ++i) { var pathFind = new MinionPathFind { query = queries[queryIndexUsed[i]], entity = findingEntities[i], completePathQueries = completePathQueries, pathsInfo = minionPathsInfo, minionPaths = minionPaths, navMeshLocation = minionNavMeshLocation, maxPathSize = SimulationState.MaxPathSize, //costs = costs, polygons = new NativeArray <PolygonId>(100, Allocator.TempJob), straightPath = new NativeArray <NavMeshLocation>(SimulationState.MaxPathSize, Allocator.TempJob), straightPathFlags = new NativeArray <StraightPathFlags>(SimulationState.MaxPathSize, Allocator.TempJob), vertexSide = new NativeArray <float>(SimulationState.MaxPathSize, Allocator.TempJob) }; // TODO: figure out how to run these in parallel, they write to different parts of the same array findHandle = pathFind.Schedule(findHandle); navMeshWorld.AddDependency(findHandle); } if (findingEntities.Length > 0) { navMeshWorld.AddDependency(findHandle); } Profiler.EndSample(); var pathFindFence = pathFollow.Schedule(minions.Length, SimulationState.BigBatchSize, findHandle); // prepare targets fence? var assignFence = assign.Schedule(formations.Length, SimulationState.BigBatchSize, inputDeps); navMeshWorld.AddDependency(pathFindFence); return(JobHandle.CombineDependencies(assignFence, pathFindFence)); }
protected override void OnCreateManager(int capacity) { var world = NavMeshWorld.GetDefaultWorld(); query = new NavMeshQuery(world, Allocator.Persistent); }
protected override void OnCreateManager(int capacity) { navMeshQuery = new NavMeshQuery(NavMeshWorld.GetDefaultWorld(), Allocator.Persistent, 128); indexMap = new NativeMultiHashMap <int, int>(100 * 1024, Allocator.Persistent); nextPositionMap = new NativeMultiHashMap <int, float3>(100 * 1024, Allocator.Persistent); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { if (!Application.isPlaying) { return(inputDeps); } if (minions.Length == 0) { return(inputDeps); // I still hate this initialization issues } // TODO maybe fix native array var forwardsBuffer = new NativeArray <Vector3>(minions.Length, Allocator.TempJob); var positionsBuffer = new NativeArray <Vector3>(minions.Length, Allocator.TempJob); var locationsBuffer = new NativeArray <NavMeshLocation>(minions.Length, Allocator.TempJob); // ============ JOB CREATION =============== var minionBehaviorJob = new MinionBehaviourJob { rigidbodyData = minions.velocities, targetPositions = minions.targets, transforms = minions.transforms, minionAttackData = minions.attackData, minionData = minions.minions, animatorData = minions.animationData, navMeshLocations = minions.navMeshLocations, forwardsBuffer = forwardsBuffer, positionsBuffer = positionsBuffer, locationsBuffer = locationsBuffer, archerAttackTime = SimulationSettings.Instance.ArcherAttackTime, dt = Time.deltaTime, randomizer = Time.frameCount, }; var minionBehaviorMoveJob = new MinionBehaviourMoveJob { positionsBuffer = positionsBuffer, locationsBuffer = locationsBuffer, query = moveLocationQuery }; var minionBehaviorSyncbackJob = new MinionBehaviourSyncbackJob { transforms = minions.transforms, navMeshLocations = minions.navMeshLocations, forwardsBuffer = forwardsBuffer, positionsBuffer = positionsBuffer, locationsBuffer = locationsBuffer }; var minionBehaviorJobFence = minionBehaviorJob.ScheduleBatch(minions.Length, SimulationState.BigBatchSize, inputDeps); minionBehaviorJobFence = minionBehaviorMoveJob.ScheduleBatch(minions.Length, SimulationState.BigBatchSize, minionBehaviorJobFence); var navMeshWorld = NavMeshWorld.GetDefaultWorld(); navMeshWorld.AddDependency(minionBehaviorJobFence); minionBehaviorJobFence = minionBehaviorSyncbackJob.ScheduleBatch(minions.Length, SimulationState.BigBatchSize, minionBehaviorJobFence); return(minionBehaviorJobFence); }
protected override JobHandle OnUpdate(JobHandle inputDeps) { // // Prepare data on the main thread // m_AfterQueriesCleanup.Complete(); m_AfterMovedRequestsForgotten.Complete(); if (m_QueryQueues.Length < k_QueryCount) { var world = NavMeshWorld.GetDefaultWorld(); if (world.IsValid()) { DisposeEverything(); Initialize(m_InitialCapacity); } } if (m_Crowd.agentNavigators.Length == 0) { return(inputDeps); } var missingAgents = m_Crowd.agentNavigators.Length - m_PlanPathForAgent.Length; if (missingAgents > 0) { AddAgents(missingAgents); } #if DEBUG_CROWDSYSTEM_ASSERTS Debug.Assert(m_Crowd.agents.Length <= m_PathRequestIdForAgent.Length && m_Crowd.agents.Length <= m_PlanPathForAgent.Length, "" + m_Crowd.agents.Length + " agents, " + m_PathRequestIdForAgent.Length + " path request IDs, " + m_PlanPathForAgent.Length + " slots for WantsPath"); if (dbgCheckRequests) { var rangeEnd = m_PathRequestsRange[k_Start] + m_PathRequestsRange[k_Count]; for (var i = m_PathRequestsRange[k_Start]; i < rangeEnd; i++) { Debug.Assert(m_PathRequests[i].uid != PathQueryQueueEcs.RequestEcs.invalidId, "Path request " + i + " should have a valid unique ID"); } } #endif #if DEBUG_CROWDSYSTEM if (drawDebug) { DrawDebug(); DrawRequestsDebug(); } #endif var requestsPerQueue = int.MaxValue; if (m_QueryQueues.Length > 0) { var existingRequests = m_QueryQueues.Sum(queue => queue.GetRequestCount()); var requestCount = existingRequests + m_PathRequestsRange[k_Count]; requestsPerQueue = requestCount / m_QueryQueues.Length; if (requestCount % m_QueryQueues.Length != 0 || requestsPerQueue == 0) { requestsPerQueue += 1; } } for (var i = 0; i < m_QueryQueues.Length; i++) { m_IsEmptyQueryQueue[i] = m_QueryQueues[i].IsEmpty(); } #if DEBUG_CROWDSYSTEM_ASSERTS if (dbgCheckRequests) { for (var i = 0; i < m_PathRequestIdForAgent.Length; i++) { var requestIdForThisAgent = m_PathRequestIdForAgent[i]; if (requestIdForThisAgent == PathQueryQueueEcs.RequestEcs.invalidId) { continue; } var existsInQ = false; var rangeEnd = m_PathRequestsRange[k_Start] + m_PathRequestsRange[k_Count]; for (var r = m_PathRequestsRange[k_Start]; r < rangeEnd; r++) { var reqInQ = m_PathRequests[r]; existsInQ = reqInQ.uid == requestIdForThisAgent; if (existsInQ) { break; } } if (!existsInQ) { foreach (var query in m_QueryQueues) { existsInQ = query.DbgRequestExistsInQueue(requestIdForThisAgent); if (existsInQ) { break; } } } Debug.Assert(existsInQ, "The request for agent " + i + " doesn't exist in any query queue anymore. UID=" + requestIdForThisAgent); } } #endif // // Begin scheduling jobs // //var pathNeededJob = new CheckPathNeededJob //{ // agentNavigators = m_Crowd.agentNavigators, // planPathForAgent = m_PlanPathForAgent, // pathRequestIdForAgent = m_PathRequestIdForAgent, // paths = m_AgentPaths.GetReadOnlyData() //}; //var afterPathNeedChecked = pathNeededJob.Schedule(m_Crowd.agents.Length, k_AgentsBatchSize, inputDeps); var makeRequestsJob = new MakePathRequestsJob { query = m_NavMeshQuery, agents = m_Crowd.agents, agentNavigators = m_Crowd.agentNavigators, planPathForAgent = m_EmptyPlanPathForAgent, pathRequestIdForAgent = m_PathRequestIdForAgent, pathRequests = m_PathRequests, pathRequestsRange = m_PathRequestsRange, currentAgentIndex = m_CurrentAgentIndex, uniqueIdStore = m_UniqueIdStore }; var afterRequestsCreated = makeRequestsJob.Schedule(inputDeps); var afterRequestsMovedToQueries = afterRequestsCreated; if (m_QueryQueues.Length > 0) { foreach (var queue in m_QueryQueues) { var enqueuingJob = new EnqueueRequestsInQueriesJob { pathRequests = m_PathRequests, pathRequestsRange = m_PathRequestsRange, maxRequestsInQueue = requestsPerQueue, queryQueue = queue }; afterRequestsMovedToQueries = enqueuingJob.Schedule(afterRequestsMovedToQueries); } } var forgetMovedRequestsJob = new ForgetMovedRequestsJob { pathRequests = m_PathRequests, pathRequestsRange = m_PathRequestsRange }; m_AfterMovedRequestsForgotten = forgetMovedRequestsJob.Schedule(afterRequestsMovedToQueries); var queriesScheduled = 0; for (var i = 0; i < m_QueryJobs.Length; ++i) { if (m_IsEmptyQueryQueue[i]) { continue; } m_AfterQueriesProcessed[i] = m_QueryJobs[i].Schedule(afterRequestsMovedToQueries); queriesScheduled++; } var afterQueriesProcessed = queriesScheduled > 0 ? JobHandle.CombineDependencies(m_AfterQueriesProcessed) : afterRequestsMovedToQueries; var afterPathsAdded = afterQueriesProcessed; foreach (var queue in m_QueryQueues) { var resultsJob = new ApplyQueryResultsJob { queryQueue = queue, paths = m_Crowd.paths, agentNavigators = m_Crowd.agentNavigators }; afterPathsAdded = resultsJob.Schedule(afterPathsAdded); } var advance = new AdvancePathJob { agents = m_Crowd.agents, agentNavigators = m_Crowd.agentNavigators, paths = m_Crowd.paths }; var afterPathsTrimmed = advance.Schedule(m_Crowd.agents.Length, k_AgentsBatchSize, afterPathsAdded); const int maxCornersPerAgent = 2; var totalCornersBuffer = m_Crowd.agents.Length * maxCornersPerAgent; var vel = new UpdateVelocityJob { query = m_NavMeshQuery, agents = m_Crowd.agents, agentNavigators = m_Crowd.agentNavigators, paths = m_Crowd.paths, straightPath = new NativeArray <NavMeshLocation>(totalCornersBuffer, Allocator.TempJob), straightPathFlags = new NativeArray <StraightPathFlags>(totalCornersBuffer, Allocator.TempJob), vertexSide = new NativeArray <float>(totalCornersBuffer, Allocator.TempJob) }; var afterVelocitiesUpdated = vel.Schedule(m_Crowd.agents.Length, k_AgentsBatchSize, afterPathsTrimmed); var move = new MoveLocationsJob { query = m_NavMeshQuery, agents = m_Crowd.agents, dt = Time.deltaTime }; var afterAgentsMoved = move.Schedule(m_Crowd.agents.Length, k_AgentsBatchSize, afterVelocitiesUpdated); #if DEBUG_CROWDSYSTEM_LOGS if (dbgPrintRequests) { afterPathsAdded.Complete(); PrintRequestsDebug(); } #endif var cleanupFence = afterPathsAdded; foreach (var queue in m_QueryQueues) { var queryCleanupJob = new QueryCleanupJob { queryQueue = queue, pathRequestIdForAgent = m_PathRequestIdForAgent }; cleanupFence = queryCleanupJob.Schedule(cleanupFence); m_AfterQueriesCleanup = cleanupFence; } //NavMeshWorld.GetDefaultWorld().AddDependency(afterAgentsMoved); return(afterAgentsMoved); }
protected override void OnUpdate() { var commandBuffer = barrier.CreateCommandBuffer().AsParallelWriter(); var localToWorldFromEntity = GetComponentDataFromEntity <LocalToWorld>(true); var translationFromEntity = GetComponentDataFromEntity <Translation>(true); var jumpingFromEntity = GetComponentDataFromEntity <NavJumping>(true); var pathBufferFromEntity = GetBufferFromEntity <NavPathBufferElement>(); var jumpBufferFromEntity = GetBufferFromEntity <NavJumpBufferElement>(); var navMeshQueryPointerArray = World.GetExistingSystem <NavMeshQuerySystem>().PointerArray; Entities .WithNone <NavHasProblem>() .WithAll <NavPlanning, LocalToParent>() .WithReadOnly(localToWorldFromEntity) .WithReadOnly(jumpingFromEntity) .WithNativeDisableParallelForRestriction(pathBufferFromEntity) .WithNativeDisableParallelForRestriction(jumpBufferFromEntity) .WithNativeDisableParallelForRestriction(navMeshQueryPointerArray) .ForEach((Entity entity, int entityInQueryIndex, int nativeThreadIndex, ref NavAgent agent, in Parent surface) => { if ( surface.Value.Equals(Entity.Null) || agent.DestinationSurface.Equals(Entity.Null) || !localToWorldFromEntity.HasComponent(surface.Value) || !localToWorldFromEntity.HasComponent(agent.DestinationSurface) ) { return; } var agentPosition = localToWorldFromEntity[entity].Position; var worldPosition = agentPosition; var worldDestination = NavUtil.MultiplyPoint3x4( localToWorldFromEntity[agent.DestinationSurface].Value, agent.LocalDestination ); var jumping = jumpingFromEntity.HasComponent(entity); if (jumping) { worldPosition = worldDestination; worldDestination = agentPosition; } var navMeshQueryPointer = navMeshQueryPointerArray[nativeThreadIndex]; UnsafeUtility.CopyPtrToStructure(navMeshQueryPointer.Value, out NavMeshQuery navMeshQuery); var status = navMeshQuery.BeginFindPath( navMeshQuery.MapLocation(worldPosition, Vector3.one * NavConstants.PATH_SEARCH_MAX, agent.TypeID), navMeshQuery.MapLocation(worldDestination, Vector3.one * NavConstants.PATH_SEARCH_MAX, agent.TypeID), NavMesh.AllAreas ); while (NavUtil.HasStatus(status, PathQueryStatus.InProgress)) { status = navMeshQuery.UpdateFindPath( NavConstants.ITERATION_MAX, out int iterationsPerformed ); } if (!NavUtil.HasStatus(status, PathQueryStatus.Success)) { commandBuffer.RemoveComponent <NavPlanning>(entityInQueryIndex, entity); commandBuffer.RemoveComponent <NavNeedsDestination>(entityInQueryIndex, entity); commandBuffer.AddComponent <NavHasProblem>(entityInQueryIndex, entity, new NavHasProblem { Value = status }); return; } navMeshQuery.EndFindPath(out int pathLength); var polygonIdArray = new NativeArray <PolygonId>( NavConstants.PATH_NODE_MAX, Allocator.Temp ); navMeshQuery.GetPathResult(polygonIdArray); var len = pathLength + 1; var straightPath = new NativeArray <NavMeshLocation>(len, Allocator.Temp); var straightPathFlags = new NativeArray <StraightPathFlags>(len, Allocator.Temp); var vertexSide = new NativeArray <float>(len, Allocator.Temp); var straightPathCount = 0; status = PathUtils.FindStraightPath( navMeshQuery, worldPosition, worldDestination, polygonIdArray, pathLength, ref straightPath, ref straightPathFlags, ref vertexSide, ref straightPathCount, NavConstants.PATH_NODE_MAX ); var jumpBuffer = !jumpBufferFromEntity.HasComponent(entity) ? commandBuffer.AddBuffer <NavJumpBufferElement>(entityInQueryIndex, entity) : jumpBufferFromEntity[entity]; var pathBuffer = !pathBufferFromEntity.HasComponent(entity) ? commandBuffer.AddBuffer <NavPathBufferElement>(entityInQueryIndex, entity) : pathBufferFromEntity[entity]; if (jumping) { var lastValidPoint = float3.zero; for (int i = 0; i < straightPath.Length; ++i) { if (navMeshQuery.IsValid(straightPath[i].polygon)) { lastValidPoint = straightPath[i].position; } else { break; } } jumpBuffer.Add( NavUtil.MultiplyPoint3x4( math.inverse(localToWorldFromEntity[agent.DestinationSurface].Value), (float3)lastValidPoint + agent.Offset ) ); if (jumpBuffer.Length > 0) { commandBuffer.RemoveComponent <NavPlanning>(entityInQueryIndex, entity); commandBuffer.AddComponent <NavLerping>(entityInQueryIndex, entity); } } else if (status == PathQueryStatus.Success) { pathBuffer.Clear(); agent.PathBufferIndex = 0; for (int i = 0; i < straightPathCount; ++i) { pathBuffer.Add( NavUtil.MultiplyPoint3x4( math.inverse(localToWorldFromEntity[surface.Value].Value), (float3)straightPath[i].position + agent.Offset ) ); } if (pathBuffer.Length > 0) { commandBuffer.RemoveComponent <NavPlanning>(entityInQueryIndex, entity); commandBuffer.AddComponent <NavLerping>(entityInQueryIndex, entity); } } polygonIdArray.Dispose(); straightPath.Dispose(); straightPathFlags.Dispose(); vertexSide.Dispose(); }) .WithName("NavPlanJob") .ScheduleParallel(); NavMeshWorld.GetDefaultWorld().AddDependency(Dependency); barrier.AddJobHandleForProducer(Dependency); }