/// <summary> /// Tests the navmesh point for equality. /// </summary> /// <param name="obj">The point to compare.</param> /// <returns>True if each element of the point is equal to this point.</returns> public override bool Equals(object obj) { if (obj is NavmeshPoint) { NavmeshPoint u = (NavmeshPoint)obj; return(point == u.point && polyRef == u.polyRef); } return(false); }
/// <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> /// Resets the corridor to the specified position. /// </summary> /// <remarks> /// <para> /// This method sets the position and target to the specified location, and reduces the /// corridor to the location's polygon. (Path size = 1) /// </para> /// <para> /// This method does not perform any validation of the input data. /// </para> /// </remarks> /// <param name="position">The position of the client.</param> public void Reset(NavmeshPoint position) { PathCorridorEx.dtpcReset(mRoot, position); mPosition = position; mTarget = position; mCorners.cornerCount = 1; mCorners.verts[0] = position.point; mCorners.flags[0] = WaypointFlag.Start | WaypointFlag.End; mCorners.polyRefs[0] = position.polyRef; }
/// <summary> /// Sets the specified resources and resets the corridor. /// </summary> /// <remarks> /// <para> /// This method is useful when pooling path corridors for use by mulitple clients. /// </para> /// <para> /// See <see cref="Reset"/> for information on the effect of the reset. /// </para> /// <para> /// Existing references will be replaced by the new references. /// </para> /// <para> /// This method cannot be used to set references to null. Attempting to do so will result /// in a failure. /// </para> /// </remarks> /// <param name="corridor">The corridor to update.</param> /// <param name="position">The position to reset to corridor to.</param> /// <param name="query">The query object to use.</param> /// <param name="filter">The filter object to use.</param> /// <returns>True if successful.</returns> public static bool LoadLocals(PathCorridor corridor, NavmeshPoint position , NavmeshQuery query, NavmeshQueryFilter filter) { // Basic checks first. if (position.polyRef == 0 || corridor == null || query == null || filter == null) { return(false); } // Validate optional parameters. // Assign and reset. corridor.mQuery = query; corridor.mFilter = filter; corridor.Reset(position); return(true); }
/// <summary> /// Casts a 'walkability' ray along the surface of the navigation mesh from the start point /// toward the end point. /// </summary> /// <remarks> /// <para> /// This method is meant to be used for quick short distance checks. /// </para> /// <para> /// If the path buffer is too small to hold the result, it will be filled as far as /// possible from the start point toward the end point.</para> /// <para> /// <b>Using the Hit Paramter</b></para> /// <para> /// If the hit parameter is a very high value (>1E38), then the ray has hit the /// end point. In this case the path represents a valid corridor to the end point and /// the value of hitNormal is undefined. /// </para> /// <para> /// If the hit parameter is zero, then the start point is on the border that was hit /// and the value of hitNormal is undefined. /// </para> /// <para> /// If <c>0 < hitParameter < 1.0 </c> then the following applies:</para> /// <code> /// distanceToHitBorder = distanceToEndPoint * hitParameter /// hitPoint = startPoint + (endPoint - startPoint) * hitParameter /// </code> /// <para> /// <b>Use Case Restriction</b> /// </para> /// <para> /// The raycast ignores the y-value of the end point. (2D check) This places /// significant limits on how it can be used. Example scenario:</para> /// <para> /// Consider a scene where there is a main floor with a second floor balcony that /// hangs over the main floor. So the first floor mesh extends below the balcony mesh. /// The start point is somewhere on the first floor. The end point is on the balcony. /// </para> /// <para> /// The raycast will search toward the end point along the first floor mesh. If it /// reaches the end point's xz-coordinates it will indicate 'no hit', meaning it reached /// the end point. /// </para> /// </remarks> /// <param name="start"> /// A point within the start polygon representing the start of the ray. /// </param> /// <param name="end">The point to cast the ray toward.</param> /// <param name="filter">The filter to apply to the query.</param> /// <param name="hitParameter">The hit parameter. (>1E38 if no hit.)</param> /// <param name="hitNormal">The normal of the nearest wall hit.</param> /// <param name="path"> /// The references of the visited polygons. [(polyRef) * pathCount] (Optional) /// </param> /// <param name="pathCount">The number of visited polygons.</param> /// <returns>The <see cref="NavStatus" /> flags for the query.</returns> public NavStatus Raycast(NavmeshPoint start, Vector3 end , NavmeshQueryFilter filter , out float hitParameter, out Vector3 hitNormal , uint[] path, out int pathCount) { pathCount = 0; hitParameter = 0; hitNormal = Vector3Util.Zero; int maxCount = (path == null ? 0 : path.Length); return NavmeshQueryEx.dtqRaycast(root , start , ref end , filter.root , ref hitParameter , ref hitNormal , path , ref pathCount , maxCount); }
/// <summary> /// Finds the polygon path from the start to the end polygon. /// </summary> /// <remarks> /// <para> /// This method is useful if the polygon reference of either the /// <paramref name="start"/> or <paramref name="end"/> point is not known. If both points /// have a polygon reference of zero, then this method is equivalent to the following: /// </para> /// <ol> /// <li> /// Using <see cref="GetNearestPoint(uint, Vector3, out Vector3)"/> with the /// <paramref name="start"/> point to get the start polygon. /// </li> /// <li> /// Using <see cref="GetNearestPoint(uint, Vector3, out Vector3)"/> with the /// <paramref name="end"/> point to get the end polygon. /// </li> /// <li>Calling the normal find path using the two new start and end points.</li> /// </ol> /// <para> /// <em>A point search will only be performed for points with a polygon reference /// of zero.</em> If a point search is required, the point and its polygon reference /// parameter become output parameters and the point will be snapped to the navigation mesh. /// </para> /// <para> /// This method may return a partial result, even if there is a failure. If there is /// no failure, it will at least perform the required point searches. If the point /// searches succeed, then the find path operation will be performed. /// </para> /// <para> /// Checking the return results: /// </para> /// <ul> /// <li>If the <paramref name="pathCount"/> is greater than zero, then the path and all /// required point searches succeeded.</li> /// <li>If the overall operation failed, but a point with an input polygon reference of /// zero has an output polygon reference that is non-zero, then that point's search /// succeeded.</li> /// </ul> /// <para> /// For the path results: /// </para> /// <para> /// If the end polygon cannot be reached, then the last polygon is the nearest one /// found to the end polygon. /// </para> /// <para> /// If the path buffer is to small to hold the result, it will be filled as far as /// possible from the start polygon toward the end polygon.</para> /// <para> /// The start and end points are used to calculate traversal costs. /// (y-values matter.) /// </para> /// </remarks> /// <param name="start"> /// A point within the start polygon. (In) (Out if the polygon reference is zero.) /// </param> /// <param name="end"> /// A point within the end polygon. (In) (Out if the polygon reference is zero.) /// </param> /// <param name="extents"> /// The search extents to use if the start or end point polygon reference is zero. /// </param> /// <param name="filter">The filter to apply to the query.</param> /// <param name="resultPath"> /// An ordered list of polygon references in the path. (Start to end.) (Out) /// [(polyRef) * pathCount] /// </param> /// <param name="pathCount">The number of polygons in the path.</param> /// <returns>The <see cref="NavStatus" /> flags for the query.</returns> public NavStatus FindPath(ref NavmeshPoint start, ref NavmeshPoint end , Vector3 extents, NavmeshQueryFilter filter , uint[] resultPath, out int pathCount) { pathCount = 0; return NavmeshQueryEx.dtqFindPathExt(root , ref start , ref end , ref extents , filter.root , resultPath , ref pathCount , resultPath.Length); }
/// <summary> /// Finds the polygon path from the start to the end polygon. /// </summary> /// <remarks> /// <para> /// If the end polygon cannot be reached, then the last polygon is the nearest one /// found to the end polygon. /// </para> /// <para> /// If the path buffer is to small to hold the result, it will be filled as far as /// possible from the start polygon toward the end polygon. /// </para> /// <para> /// The start and end points are used to calculate traversal costs. (y-values matter.) /// </para> /// </remarks> /// <param name="start">A point within the start polygon.</param> /// <param name="end">A point within the end polygon.</param> /// <param name="filter">The filter to apply to the query.</param> /// <param name="resultPath"> /// An ordered list of polygoon references in the path. (Start to end.) (Out) /// [(polyRef) * pathCount] /// </param> /// <param name="pathCount">The number of polygons in the path.</param> /// <returns>The <see cref="NavStatus" /> flags for the query.</returns> public NavStatus FindPath(NavmeshPoint start, NavmeshPoint end , NavmeshQueryFilter filter , uint[] resultPath, out int pathCount) { pathCount = 0; return NavmeshQueryEx.dtqFindPath(root , start , end , filter.root , resultPath , ref pathCount , resultPath.Length); }
/// <summary> /// Returns the distance from the specified position to the nearest polygon wall. /// </summary> /// <remarks> /// <para> /// The closest point is not height adjusted using the detail data. /// Use <see cref="GetPolyHeight"/> if needed. /// </para> /// <para> /// The distance will equal the search radius if there is no wall within the radius. /// In this case the values of closestPoint and normal are undefined. /// </para> /// <para> /// The normal will become unpredicable if the distance is a very small number. /// </para> /// </remarks> /// <param name="searchPoint">The center of the search circle.</param> /// <param name="searchRadius">The radius of the search circle.</param> /// <param name="filter">The filter to apply to the query.</param> /// <param name="distance">Distance to nearest wall.</param> /// <param name="closestPoint">The nearest point on the wall.</param> /// <param name="normal"> /// The normalized ray formed from the wall point to the source point. /// </param> /// <returns>The <see cref="NavStatus" /> flags for the query.</returns> public NavStatus FindDistanceToWall(NavmeshPoint searchPoint , float searchRadius , NavmeshQueryFilter filter , out float distance , out Vector3 closestPoint , out Vector3 normal) { distance = 0; closestPoint = Vector3Util.Zero; normal = Vector3Util.Zero; return NavmeshQueryEx.dtqFindDistanceToWall(root , searchPoint , searchRadius , filter.root , ref distance , ref closestPoint , ref normal); }
/// <summary> /// Initializes a sliced path find query. /// </summary> /// <remarks> /// <para> /// This method will fail if <see cref="IsRestricted"/> is true. /// </para> /// <para> /// <b>Warning:</b> Calling any other query methods besides the other sliced path methods /// before finalizing this query may result in corrupted data. /// </para> /// <para> /// The filter is stored and used for the duration of the query. /// </para> /// <para> /// The standard use case: /// </para> /// <ol> /// <li>Initialize the sliced path query</li> /// <li>Call <see cref="UpdateSlicedFindPath"/> until its status returns complete.</li> /// <li>Call <see cref="FinalizeSlicedFindPath"/> to get the path.</li> /// </ol> /// </remarks> /// <param name="start">A point within the start polygon.</param> /// <param name="end">A point within the end polygon.</param> /// <param name="filter">The filter to apply to the query.</param> /// <returns>The <see cref="NavStatus" /> flags for the query.</returns> public NavStatus InitSlicedFindPath(NavmeshPoint start, NavmeshPoint end , NavmeshQueryFilter filter) { if (mIsRestricted) return NavStatus.Failure; return NavmeshQueryEx.dtqInitSlicedFindPath(root , start , end , filter.root); }
/// <summary> /// Returns a random point within reach of the specified location. /// </summary> /// <remarks> /// <para> /// The result point is constrainted to the polygons overlapped by the circle, not /// the circle itself. The overlap test follows the same rules as the FindPolys method. /// </para> /// <para> /// The search speed is linear to the number of polygons. /// </para> /// </remarks> /// <param name="start">The point to search from.</param> /// <param name="radius">The polygon overlap radius.</param> /// <param name="filter">The filter to apply to the query.</param> /// <param name="randomPoint">A random point within reach of the specified location.</param> /// <returns>The <see cref="NavStatus" /> flags for the query.</returns> public NavStatus GetRandomPoint(NavmeshPoint start, float radius , NavmeshQueryFilter filter , out NavmeshPoint randomPoint) { randomPoint = new NavmeshPoint(); return NavmeshQueryEx.dtqFindRandomPointCircle(root, start, radius , filter.root , ref randomPoint); }
/// <summary> /// Returns a random point on the navigation mesh. /// </summary> /// <remarks> /// <para> /// The search speed is linear to the number of polygons. /// </para> /// </remarks> /// <param name="filter">The filter to apply to the query.</param> /// <param name="randomPoint">A random point on the navigation mesh.</param> /// <returns>The <see cref="NavStatus" /> flags for the query.</returns> public NavStatus GetRandomPoint(NavmeshQueryFilter filter, out NavmeshPoint randomPoint) { randomPoint = new NavmeshPoint(); return NavmeshQueryEx.dtqFindRandomPoint(root, filter.root, ref randomPoint); }
/// <summary> /// Moves from the start to the end point constrained to the navigation mesh. /// </summary> /// <remarks> /// <para> /// This method is optimized for small delta movement and a small number of polygons. /// If used for too great a distance, the result will form an incomplete path.</para> /// <para> /// The result point will equal the end point if the end is reached. Otherwise the /// closest reachable point will be returned. /// </para> /// <para> /// The result position is not projected to the surface of the navigation mesh. If /// that is needed, use <see cref="GetPolyHeight"/>.</para> /// <para> /// This method treats the end point in the same manner as the <see cref="Raycast"/> /// method. (As a 2D point.) See that method's documentation for details on the impact. /// </para> /// <para> /// If the result buffer is too small to hold the entire result, it will be /// filled as far as possible from the start point toward the end point. /// </para> /// </remarks> /// <param name="start">A position within the start polygon.</param> /// <param name="end">The end position.</param> /// <param name="filter">The filter to apply to the query.</param> /// <param name="resultPoint">The result point from the move.</param> /// <param name="visitedPolyRefs">The references of the polygons /// visited during the move. [(polyRef) * visitedCount]</param> /// <param name="visitedCount">The number of polygons visited during /// the move.</param> /// <returns>The <see cref="NavStatus" /> flags for the query.</returns> public NavStatus MoveAlongSurface(NavmeshPoint start, Vector3 end , NavmeshQueryFilter filter , out Vector3 resultPoint , uint[] visitedPolyRefs, out int visitedCount) { visitedCount = 0; resultPoint = Vector3Util.Zero; return NavmeshQueryEx.dtqMoveAlongSurface(root , start , ref end , filter.root , ref resultPoint , visitedPolyRefs , ref visitedCount , visitedPolyRefs.Length); }
private SearchResult NearestPoint( NavGroup helper , ref Vector3 geomPoint , out NavmeshPoint navPoint ) { NavStatus status = helper.query.GetNearestPoint(hitPosition, helper.extents, helper.filter, out navPoint); if (NavUtil.Failed(status)) return SearchResult.HitGeometry; if (navPoint.polyRef == 0) { return SearchResult.HitGeometry; } return SearchResult.HitNavmesh; }
/// <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> /// Finds the nearest point on the surface of the navigation mesh. /// </summary> /// <remarks> /// <para> /// If the search box does not intersect any polygons the search will return success, /// but the result polygon reference will be zero. So always check the polygon reference /// before using the point data. /// </para> /// <b>Warning:</b> This function is not suitable for large area searches. If the /// search extents overlaps more than 128 polygons it may return an invalid result. /// <para> /// The detail mesh is used to correct the y-value of result. /// </para> /// </remarks> /// <param name="searchPoint">The center of the search box.</param> /// <param name="extents">The search distance along each axis.</param> /// <param name="filter">The filter to apply to the query.</param> /// <param name="result">The nearest point on the polygon.</param> /// <returns>The <see cref="NavStatus"/> flags for the query.</returns> public NavStatus GetNearestPoint(Vector3 searchPoint, Vector3 extents , NavmeshQueryFilter filter , out NavmeshPoint result) { result = NavmeshPoint.Zero; return NavmeshQueryEx.dtqFindNearestPoly(root , ref searchPoint , ref extents , filter.root , ref result); }
/// <summary> /// Creates an array of vectors from the provided navmesh points. /// </summary> /// <remarks> /// <para> /// A new array will be created if the <paramref name="target"/> array is null. /// </para> /// </remarks> /// <param name="source">The source array.</param> /// <param name="sourceIndex">The start of the copy in the source.</param> /// <param name="target">The target of the copy. (Optional)</param> /// <param name="targetIndex">The start copy location within the target.</param> /// <param name="count">The number of vectors to copy.</param> /// <returns> /// An array containing the copied vectors. (A reference to <paramref name="target"/> /// if it was non-null.) /// </returns> public static Vector3[] GetPoints(NavmeshPoint[] source, int sourceIndex , Vector3[] target, int targetIndex , int count) { if (target == null) target = new Vector3[source.Length + targetIndex]; for (int i = 0; i < count; i++) { target[targetIndex + i] = source[sourceIndex + i].point; } return target; }
/// <summary> /// Finds the non-overlapping navigation polygons in the local neighborhood around the /// specified point. /// </summary> /// <remarks> /// <para> /// This method is optimized for a small query radius and small number of result polygons. /// </para> /// <para> /// The order of the result is from least to highest cost.</para> /// <para> /// At least one result buffer must be provided.</para> /// <para> /// The primary use case for this method is for performing Dijkstra searches. /// Candidate polygons are found by searching the graph beginning at the start polygon. /// </para> /// <para> /// The same intersection test restrictions that apply to the FindPoly methods apply /// to this method. /// </para> /// <para> /// The value of the center point is used as the start point for cost calculations. /// It is not projected onto the surface of the mesh, so its y-value will effect the costs. /// </para> /// <para> /// Intersection tests occur in 2D. All polygons and the search circle are projected /// onto the xz-plane, so the y-value of the center point does not effect intersection /// tests. /// </para> /// <para> /// If the buffers are is too small to hold the entire result, they will be /// filled to capacity. /// </para> /// </remarks> /// <param name="start"> /// The center point to start from which to start the search. (Must be valid.) /// </param> /// <param name="radius">The radius of the search circle.</param> /// <param name="filter">The filter to apply to the query.</param> /// <param name="resultPolyRefs"> /// The references of the polygons touched by the circle. /// [(polyRef) * resultCount] (Optional) /// </param> /// <param name="resultParentRefs"> /// The references of the parent polygons for each result. /// Zero if a result polygon has no parent. [(parentRef) * resultCount] (Optional) /// </param> /// <param name="resultCount">The number of polygons found.</param> /// <returns>The <see cref="NavStatus" /> flags for the query.</returns> public NavStatus GetPolysLocal(NavmeshPoint start, float radius , NavmeshQueryFilter filter , uint[] resultPolyRefs, uint[] resultParentRefs, out int resultCount) { resultCount = 0; // Set max count to the smallest length. int maxCount = (resultPolyRefs == null ? 0 : resultPolyRefs.Length); maxCount = (resultParentRefs == null ? maxCount : Math.Min(maxCount, resultParentRefs.Length)); if (maxCount == 0) return (NavStatus.Failure | NavStatus.InvalidParam); return NavmeshQueryEx.dtqFindLocalNeighbourhood(root , start.polyRef , ref start.point , radius , filter.root , resultPolyRefs , resultParentRefs , ref resultCount , maxCount); }
/// <summary> /// Sets the specified resources and resets the corridor. /// </summary> /// <remarks> /// <para> /// This method is useful when pooling path corridors for use by mulitple clients. /// </para> /// <para> /// See <see cref="Reset"/> for information on the effect of the reset. /// </para> /// <para> /// Existing references will be replaced by the new references. /// </para> /// <para> /// This method cannot be used to set references to null. Attempting to do so will result /// in a failure. /// </para> /// </remarks> /// <param name="corridor">The corridor to update.</param> /// <param name="position">The position to reset to corridor to.</param> /// <param name="query">The query object to use.</param> /// <param name="filter">The filter object to use.</param> /// <returns>True if successful.</returns> public static bool LoadLocals(PathCorridor corridor, NavmeshPoint position , NavmeshQuery query, NavmeshQueryFilter filter) { // Basic checks first. if (position.polyRef == 0|| corridor == null|| query == null|| filter == null) return false; // Validate optional parameters. // Assign and reset. corridor.mQuery = query; corridor.mFilter = filter; corridor.Reset(position); return true; }
/// <summary> /// Gets the height of the polygon at the provided point using the detail mesh. /// (Most accurate.) /// </summary> /// <remarks> /// <para> /// The method will return falure if the provided point is outside the xz-column /// of the polygon. /// </para> /// </remarks> /// <param name="point">The point within the polygon's xz-column.</param> /// <param name="height">The height at the surface of the polygon. /// </param> /// <returns>The <see cref="NavStatus" /> flags for the query.</returns> public NavStatus GetPolyHeight(NavmeshPoint point, out float height) { height = 0; return NavmeshQueryEx.dtqGetPolyHeight(root , point , ref height); }