/// <summary> /// Immediately frees all unmanaged resources allocated by the object. /// </summary> public override void RequestDisposal() { // There are no managed or local allocations. if (root != IntPtr.Zero) { mFilter.RequestDisposal(); mFilter = null; mGrid.Dispose(); mGrid = null; mQuery.RequestDisposal(); mQuery = null; mNavmesh = null; mMaxAgentRadius = -1; agentStates = null; for (int i = 0; i < mAgents.Length; i++) { if (mAgents[i] == null) { continue; } mAgents[i].Dispose(); mAgents[i] = null; } CrowdManagerEx.dtcDetourCrowdFree(root); root = IntPtr.Zero; } }
/// <summary> /// Adds an agent to the manager. /// </summary> /// <param name="position"> /// The current position of the agent within the navigation mesh. /// </param> /// <param name="agentParams">The agent configuration.</param> /// <returns> /// A reference to the agent object created by the manager, or null on error. /// </returns> public CrowdAgent AddAgent(Vector3 position , CrowdAgentParams agentParams) { if (IsDisposed) { return(null); } IntPtr ptr = IntPtr.Zero; CrowdAgentCoreState initialState = new CrowdAgentCoreState(); int index = CrowdManagerEx.dtcAddAgent(root , ref position , ref agentParams , ref ptr , ref initialState); if (index == -1) { return(null); } mAgents[index] = new CrowdAgent(this, ptr, index); agentStates[index] = initialState; return(mAgents[index]); }
/// <summary> /// Gets the velocity sample count. /// </summary> /// <returns>The velocity sample count.</returns> public int GetVelocitySampleCount() { if (IsDisposed) { return(-1); } return(CrowdManagerEx.dtcGetVelocitySampleCount(root)); }
/// <summary> /// Updates the steering and positions for all agents. /// </summary> /// <param name="deltaTime">The time in seconds to update the simulation.</param> public void Update(float deltaTime) { if (IsDisposed) { return; } CrowdManagerEx.dtcUpdate(root, deltaTime, agentStates); }
/// <summary> /// Updates the configuration for an agent. /// </summary> /// <param name="config">The new agent configuration.</param> public void SetConfig(CrowdAgentParams config) { if (!IsDisposed) { CrowdManagerEx.dtcUpdateAgentParameters(mManager.root , managerIndex , ref config); } }
/// <summary> /// The extents used by the manager when it performs queries against the navigation mesh. /// </summary> /// <remarks> /// <para> /// All agents and targets should remain within these distances of the navigation mesh /// surface. For example, if the y-axis extent is 1.0, then the agent should remain /// between 1.0 above and 1.0 below the surface of the mesh. /// </para> /// <para> /// The extents remains constant over the life of the crowd manager. /// </para> /// </remarks> /// <returns>The extents.</returns> public Vector3 GetQueryExtents() { if (IsDisposed) { return(Vector3Util.Zero); } Vector3 result = Vector3Util.Zero; CrowdManagerEx.dtcGetQueryExtents(root, ref result); return(result); }
/// <summary> /// Adjusts the position of an agent's target. /// </summary> /// <remarks> /// <para> /// This method is used to make small local adjustments to the target. (Such as happens /// when following a moving target.) Use <see cref="RequestMoveTarget"/> when a new /// target is needed. /// </para> /// </remarks> /// <param name="position">The new target position.</param> /// <returns>True if the adjustment was successful.</returns> public bool AdjustMoveTarget(NavmeshPoint position) { if (IsDisposed) { return(false); } return(CrowdManagerEx.dtcAdjustMoveTarget(mManager.root , managerIndex , position)); }
/// <summary> /// Submits a new move request for the agent. /// </summary> /// <remarks> /// <para> /// This method is used when a new target is set. Use <see cref="AdjustMoveTarget"/> when /// only small local adjustments are needed. (Such as happens when following a moving /// target.) /// </para> /// <para> /// The position will be constrained to the surface of the navigation mesh. /// </para> /// <para> /// The request will be processed during the next <see cref="CrowdManager.Update"/>. /// </para> /// </remarks> /// <param name="target">The target position.</param> /// <returns>True if the target was successfully set.</returns> public bool RequestMoveTarget(NavmeshPoint target) { if (IsDisposed) { return(false); } return(CrowdManagerEx.dtcRequestMoveTarget(mManager.root , managerIndex , target)); }
/// <summary> /// Sets the shared avoidance configuration for a specified index. /// </summary> /// <remarks> /// <para> /// Multiple avoidance configurations can be set for the manager with agents assigned to /// different avoidance behaviors via the <see cref="CrowdAgentParams"/> object. /// </para> /// </remarks> /// <param name="index"> /// The index. [Limits: 0 <= value < <see cref="MaxAvoidanceParams"/>]. /// </param> /// <param name="config">The avoidance configuration.</param> /// <returns>True if the configuration is successfully set.</returns> public bool SetAvoidanceConfig(int index , CrowdAvoidanceParams config) { if (IsDisposed || index < 0 || index >= MaxAvoidanceParams) { return(false); } CrowdManagerEx.dtcSetObstacleAvoidanceParams(root, index, config); return(true); }
/// <summary> /// Removes an agent from the manager. /// </summary> /// <remarks> /// <para> /// The <see cref="CrowdAgent"/> object will be immediately disposed. Continued use will /// result in undefined behavior. /// </para> /// </remarks> /// <param name="agent">The agent to remove.</param> public void RemoveAgent(CrowdAgent agent) { for (int i = 0; i < mAgents.Length; i++) { if (mAgents[i] == agent) { CrowdManagerEx.dtcRemoveAgent(root, agent.managerIndex); agent.Dispose(); mAgents[i] = null; // Don't need to do anything about the core data array. } } }
/// <summary> /// Gets the shared avoidance configuration for a specified index. /// </summary> /// <remarks> /// <para> /// Getting a configuration for an index that has not been set will return a configuration /// in an undefined state. /// </para> /// </remarks> /// <param name="index"> /// The index. [Limits: 0 <= value < <see cref="MaxAvoidanceParams"/>] /// </param> /// <returns>An avoidance configuration.</returns> public CrowdAvoidanceParams GetAvoidanceConfig(int index) { if (!IsDisposed && index >= 0 && index < MaxAvoidanceParams) { CrowdAvoidanceParams result = new CrowdAvoidanceParams(); CrowdManagerEx.dtcGetObstacleAvoidanceParams(root , index , result); return(result); } return(null); }
/// <summary> /// Creates a new crowd manager. /// </summary> /// <param name="maxAgents"> /// The maximum number of agents that can be added to the manager. /// </param> /// <param name="maxAgentRadius">The maximum allowed agent radius.</param> /// <param name="navmesh"> /// The navigation mesh to use for path planning and steering related queries. /// </param> /// <returns>A new crowd manager, or null on error.</returns> public static CrowdManager Create(int maxAgents, float maxAgentRadius, Navmesh navmesh) { if (navmesh == null || navmesh.IsDisposed) { return(null); } maxAgents = Math.Max(1, maxAgents); maxAgentRadius = Math.Max(0, maxAgentRadius); IntPtr root = CrowdManagerEx.dtcDetourCrowdAlloc(maxAgents, maxAgentRadius, navmesh.root); if (root == IntPtr.Zero) { return(null); } return(new CrowdManager(root, navmesh, maxAgents, maxAgentRadius)); }
private CrowdManager(IntPtr crowd, Navmesh navmesh, int maxAgents, float maxAgentRadius) : base(AllocType.External) { mMaxAgentRadius = maxAgentRadius; mNavmesh = navmesh; root = crowd; mAgents = new CrowdAgent[maxAgents]; agentStates = new CrowdAgentCoreState[maxAgents]; IntPtr ptr = CrowdManagerEx.dtcGetFilter(root); mFilter = new NavmeshQueryFilter(ptr, AllocType.ExternallyManaged); ptr = CrowdManagerEx.dtcGetGrid(root); mGrid = new CrowdProximityGrid(ptr); ptr = CrowdManagerEx.dtcGetNavMeshQuery(root); mQuery = new NavmeshQuery(ptr, true, AllocType.ExternallyManaged); }