public NavigationEngine(Navmesh navmesh) { m_Navmesh = navmesh; UpdatesThread = new Thread(Updates); UpdatesThread.Name = "Navigator-UpdatesThread"; UpdatesThread.Start(); Precision = 8; GridCellPrecision = 40; ExploreCellPrecision = 25; PathRandomCoeff = 0; PathNodesShiftDist = 5; CurrentPosDiffRecalcThreshold = 20; UpdatePathInterval = -1; EnableAntiStuck = false; IsStandingOnPurpose = true; MovementFlags = MovementFlag.Walk; }
void OnRenderObject() { if (!mDebugEnabled) { return; } INavmeshData data = NavmeshData; if (!mNavmeshData || !data.HasNavmesh) { mDebugMesh = null; return; } if (mDebugMesh == null || data.Version != mDebugVersion) { mDebugMesh = data.GetNavmesh(); mDebugVersion = data.Version; if (mDebugMesh == null) { return; } } NavDebug.Draw(mDebugMesh, false); }
/// <summary> /// Reports all edges intersecting specified ray while ISegmentCast.RegisterCollision returns true. /// Collisions are reported in order of their distance from rayCast.Origin. /// </summary> /// <param name="segmentCast">Cast data</param> /// <param name="open">NativeList for internal use, is cleared before use</param> public static void CastRay <T>(this Navmesh navmesh, T rayCast, NativeList <IntPtr> open) where T : IRayCast { Assert.IsTrue(rayCast.Distance >= 0, "Ray cast distance should be larger than or equal to zero"); Assert.IsTrue(math.abs(1 - math.length(rayCast.Direction)) < .001f, "Ray cast direction should be normalized"); open.Clear(); var h = navmesh.Max; var dist = math.min(math.max(h.x, h.y) * 4, rayCast.Distance); var org = rayCast.Origin; var dest = org + rayCast.Direction * dist; if (!navmesh.Contains(dest)) { var d = dest; if (!IntersectSegSeg(org, d, -h, new double2(h.x, -h.y), out dest) && !IntersectSegSeg(org, d, new double2(h.x, -h.y), h, out dest) && !IntersectSegSeg(org, d, h, new double2(-h.x, h.y), out dest)) { IntersectSegSeg(org, d, new double2(-h.x, h.y), -h, out dest); } } var segmentCast = new RayCastWrapper <T>(dest, rayCast); navmesh.CastSegment(segmentCast, open); }
public void Init(Navmesh navMesh, int maxAgent = 100, float maxAgentRaidus = 45f) { m_MaxAgent = maxAgent; m_MaxAgentRadius = maxAgentRaidus; m_NavMesh = navMesh; Init(); }
protected override void OnUpdate() { var ecbSource = DotsNavSystemGroup.EcbSource; var buffer = ecbSource.CreateCommandBuffer().AsParallelWriter(); Entities .WithBurst() .WithNone <Navmesh>() .ForEach((Entity entity, int entityInQueryIndex, in NavmeshComponent data) => { var resources = new Navmesh(); resources.Allocate(data); buffer.AddComponent(entityInQueryIndex, entity, resources); }) .ScheduleParallel(); buffer = ecbSource.CreateCommandBuffer().AsParallelWriter(); Entities .WithBurst() .WithNone <NavmeshComponent>() .ForEach((Entity entity, int entityInQueryIndex, Navmesh resources) => { resources.Dispose(); buffer.RemoveComponent <Navmesh>(entityInQueryIndex, entity); }) .Schedule(); ecbSource.AddJobHandleForProducer(Dependency); }
void IsCdt(ref Navmesh lct, int constraint = -1, int vertex = -1) { var e = lct.GetEdgeEnumerator(true); while (e.MoveNext()) { if (e.Current->Constrained) { continue; } var o = e.Current->Org->Point; var d = e.Current->Dest->Point; if (Math.Contains(o, lct.Min, lct.Max) && Math.Contains(d, lct.Min, lct.Max)) { var on = e.Current->ONext->Dest->Point; var dn = e.Current->DNext->Org->Point; if (Math.CircumcircleContains(o, d, on, dn) && Math.Ccw(dn, d, on) && Math.Ccw(on, o, dn)) { Debug.Log($"delaunay fail, constraint: {constraint}, vertex:{vertex}, from: {o}, to: {d}"); throw new Exception(); } } } }
/// <summary> /// Loads a single-tile navigation mesh from the provided data. /// </summary> /// <param name="buildData">The tile build data.</param> /// <param name="buildConfig">The build information. (Optional)</param> /// <returns>The <see cref="NavStatus"/> flags for the operation.</returns> public NavStatus Load(NavmeshTileBuildData buildData, NavmeshBuildInfo buildConfig) { if (buildData == null || buildData.IsDisposed) { return(NavStatus.Failure | NavStatus.InvalidParam); } Navmesh navmesh; NavStatus status = Navmesh.Create(buildData, out navmesh); if ((status & NavStatus.Sucess) == 0) { return(status); } mDataPack = navmesh.GetSerializedMesh(); if (mDataPack == null) { return(NavStatus.Failure); } mBuildInfo = buildConfig; mVersion++; return(NavStatus.Sucess); }
/// <summary> /// Load a navigation mesh from data created from the <see cref="Navmesh.GetSerializedMesh"/> /// method. /// </summary> /// <param name="serializedMesh">The serialized mesh.</param> /// <param name="buildConfig">The build information. (Optional)</param> /// <returns>The <see cref="NavStatus"/> flags for the operation.</returns> public NavStatus Load(byte[] serializedMesh, NavmeshBuildInfo buildConfig) { if (serializedMesh == null) { return(NavStatus.Failure | NavStatus.InvalidParam); } // This roundabout method is used for validation. Navmesh navmesh; NavStatus status = Navmesh.Create(serializedMesh, out navmesh); if ((status & NavStatus.Sucess) == 0) { return(status); } mDataPack = navmesh.GetSerializedMesh(); if (mDataPack == null) { return(NavStatus.Failure); } mBuildInfo = buildConfig; mVersion++; return(NavStatus.Sucess); }
private void OnSceneGUI(SceneView sceneView) { if (!(ScriptableObject)mNavmeshData) { Hide(); return; } if (!mNavmeshData.HasNavmesh) { mDataVersion = -1; mNavmesh = null; return; } if (mNavmesh == null || mNavmeshData.Version != mDataVersion) { mNavmesh = mNavmeshData.GetNavmesh(); mDataVersion = mNavmeshData.Version; if (mNavmesh == null) { return; } } NavDebug.Draw(mNavmesh, mColorByArea); }
/// <summary> /// Reports all edges intersecting specified ray while ISegmentCast.RegisterCollision returns true. /// Collisions are reported in order of their distance from rayCast.Origin. /// </summary> /// <param name="segmentCast">Cast data</param> /// <param name="allocator">Allocator used to create internal buffers</param> public static void CastRay <T>(this Navmesh navmesh, T rayCast, Allocator allocator) where T : IRayCast { var open = new NativeList <IntPtr>(allocator); navmesh.CastRay(rayCast, open); open.Dispose(); }
internal bool SetConfigFromTarget(BuildContext context) { if (mBuildData.IsValid) { // Can't do it while in buildable state. return(false); } if (!CanLoadFromTarget(context, false)) { return(false); } Navmesh navmesh = BuildTarget.GetNavmesh(); if (navmesh == null) { context.LogError("Build target does not have an existing navigation mesh. (It lied.)" , this); return(false); } SetConfigFromTargetIntern(navmesh); return(true); }
public Battle(BattleParams param, Navmesh navmesh, LuaEnv luaEnv) { this.rid = param.id; this.data = ModelFactory.GetBattleData(Utils.GetIDFromRID(this.rid)); this._luaEnv = luaEnv; this._context = new UpdateContext(); this._entityManager = new EntityManager(this); this._buffManager = new BuffManager(this); this._random = new ConsistentRandom(param.rndSeed); this._pathManager = new NavMeshProxy(); this._timer0 = new TimeScheduler(); this._pathManager.Create(navmesh); if (!string.IsNullOrEmpty(this.data.script)) { this._script = new Script(this, this._luaEnv, this.data.script); this._script.Call(Script.S_ON_BATTLE_INITIALIZED); } this.CreatePlayers(param); foreach (KeyValuePair <string, BattleData.Structure> kv in this.data.structures) { BattleData.Structure def = this.data.structures[kv.Key]; this.CreateBio(def.id, def.pos, def.dir, def.team); } foreach (KeyValuePair <string, BattleData.Neutral> kv in this.data.neutrals) { BattleData.Neutral def = this.data.neutrals[kv.Key]; this.CreateBio(def.id, def.pos, def.dir, def.team); } }
/// <summary> /// Reports all edges intersecting specified line segment while ISegmentCast.RegisterCollision returns true. /// Collisions are reported in order of their distance from segmentCast.Origin. /// </summary> /// <param name="segmentCast">Cast data</param> /// <param name="allocator">Allocator used to create internal buffers</param> public static void CastSegment <T>(this Navmesh navmesh, T segmentCast, Allocator allocator) where T : ISegmentCast { var open = new NativeList <IntPtr>(allocator); navmesh.CastSegment(segmentCast, open); open.Dispose(); }
void TestDisturbances(ref Navmesh lct) { _disturbances.Clear(); var e = lct.GetEdgeEnumerator(true); while (e.MoveNext()) { if (e.Current->Constrained) { continue; } lct.CheckEdgeForDisturbances(e.Current, _disturbances); for (int j = 0; j < _disturbances.Length; j++) { var p = _disturbances[j].Vertex->Point; var o = _disturbances[j].Edge->Org->Point; var d = _disturbances[j].Edge->Dest->Point; Debug.Log($"Edge {o} => {d} disturbed by {p}"); } Assert.IsTrue(_disturbances.Length == 0); } }
void Awake() { meshGenerator = this; mesh = new Mesh(); mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; // Vector3 position = new Vector3(-xSize * width / 2f, 0f, -zSize * length / 2f); // meshFilter.transform.Translate(position, Space.World); // material.SetFloat("TerraceHeight", terraceHeight); material.SetFloat("Height", height); // StartCoroutine(IEnumerable CreateShapeCoroutine()); GenerateLand(); UpdateMesh(); meshFilter.mesh = mesh; meshCollider.sharedMesh = mesh; navmesh = new Navmesh(vertices, xSize, zSize, width, length); // int testVertex = (9 * xSize / 10) * (9 * zSize / 10); // Vector3 testVertex = navmesh.findClosestVertex(new Vector3(24.4f, 1f, 24.4f)); // // Debug.Log("Closest Vertex: " + testVertex.ToString()); // paths = new Stack<Vector3>[navigators.Length]; // int index = 0; // foreach (Transform navigator in navigators) // { // navigator.position = testVertex + transform.position; // paths[index] = navmesh.getSmartPath(testVertex, vertices[0]); // index ++; // } // path = navmesh.getPath(testVertex, vertices[0]); }
public static Pathfinder Create(string filePath) { BinaryFormatter formatter = new BinaryFormatter(); FileStream stream = null; if (!File.Exists(filePath)) { return(null); } try { stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read); NavStatus status = Navmesh.Create((byte[])formatter.Deserialize(stream), out Navmesh navMesh); if (status == NavStatus.Sucess) { return(new Pathfinder(navMesh)); } } finally { if (stream != null) { stream.Close(); } } return(null); }
private float _elapsedtime; //出現時間 private void Start() { _navmesh_obj = GameObject.Find("Spawner"); _navmesh = gameObject.GetComponent <Navmesh>(); _numberofenemys = 0; _elapsedtime = 0.0f; }
/// <summary> /// Copy constructor. /// </summary> /// <param name="copy">The group to copy.</param> /// <param name="cloneFilter"> /// If true, the filter will be cloned. Otherwise it will be referenced. /// </param> public NavGroup(NavGroup copy, bool cloneFilter) { this.mesh = copy.mesh; this.query = copy.query; this.crowd = copy.crowd; this.filter = (cloneFilter ? copy.filter.Clone() : copy.filter); this.extents = copy.extents; }
public static CrowdMoveMgr Create(Navmesh navMesh, int maxAgent = 100, float maxAgentRaidus = 45f) { GameObject gameObj = new GameObject("CrowdMoveMgr", typeof(CrowdMoveMgr)); CrowdMoveMgr mgr = gameObj.GetComponent <CrowdMoveMgr>(); mgr.Init(navMesh, maxAgent, maxAgentRaidus); return(mgr); }
public AIMesh() { navmesh = null; AIMeshVertexData = new List <Vector3>(); AIMeshIndicsData = new List <AIMeshIndexData>(); AIMeshVertics = new List <AIMeshVertex>(); AIMeshEdges = new List <AIMeshEdge>(); }
/// <summary> /// Draws a debug visualization of the navigation mesh. /// </summary> /// <param name="mesh">The mesh to draw.</param> /// <param name="colorByArea"> /// If true, will be colored by polygon area. If false, will be colored by tile index. /// </param> public static void Draw(Navmesh mesh, bool colorByArea) { int count = mesh.GetMaxTiles(); for (int i = 0; i < count; i++) { Draw(mesh.GetTile(i), null, null, 0, colorByArea ? -1 : i); } }
/// <summary> /// Reports all edges intersecting specified disc while IDiscCast.RegisterCollision returns true. /// A NativeQueue and NativeHashSet will be created with the specified allocator, and disposed before returning. /// </summary> /// <param name="discCast">Cast data</param> /// <param name="allocator">Allocator used to create internal buffers</param> public static void CastDisc <T>(this Navmesh navmesh, T discCast, Allocator allocator) where T : IDiscCast { var open = new NativeList <IntPtr>(allocator); var closed = new NativeHashSet <int>(32, allocator); navmesh.CastDisc(discCast, open, closed); open.Dispose(); closed.Dispose(); }
/// <summary> /// Draws a debug visualization of the navigation mesh with the closed nodes highlighted. /// </summary> /// <param name="mesh">The mesh to draw.</param> /// <param name="query">The query which provides the list of closed nodes.</param> public static void Draw(Navmesh mesh, NavmeshQuery query) { int count = mesh.GetMaxTiles(); for (int i = 0; i < count; i++) { Draw(mesh.GetTile(i), query, null, 0, i); } }
public void Create(Navmesh navmesh) { this._navmesh = navmesh; //一定要保存起来,Navmesh的析构函数会把非托管内存的指针清掉!! NavStatus status = NavmeshQuery.Create(navmesh, 2048, out this._query); if (status != NavStatus.Sucess) { LLogger.Error(status); } }
/// <summary> /// Constructor. /// </summary> /// <param name="mesh">The navigation mesh used by the query.</param> /// <param name="query">A navigation mesh query.</param> /// <param name="crowd">A crowd.</param> /// <param name="filter">The filter to use with the query.</param> /// <param name="extents">The extents to use with the query.</param> /// <param name="cloneFilter"> /// If true, the filter will be cloned rather than referenced. /// </param> public NavGroup(Navmesh mesh, NavmeshQuery query, CrowdManager crowd , NavmeshQueryFilter filter, Vector3 extents , bool cloneFilter) { this.mesh = mesh; this.query = query; this.crowd = crowd; this.filter = (cloneFilter ? filter.Clone() : filter); this.extents = extents; }
public LctValidator(ref Navmesh navmesh, Allocator allocator) { _triangles = new HashSet <int>(1024, allocator); _removedTriangles = new NativeList <int>(1024, allocator); _closed = new HashSet <IntPtr>(1024, allocator); _disturbances = new NativeList <Disturbance>(allocator); _unconstrained = new NativeList <IntPtr>(allocator); _clearanceCalculated = new NativeArray <int>(1, allocator); _previousTriangles = default; InitTriangles(ref navmesh); }
/// <summary> /// Generates a human readable report of the mesh data. /// </summary> /// <returns>A human readable report of the mesh data.</returns> public string GetMeshReport() { if (!HasNavmesh) { return("No mesh."); } Navmesh nm = GetNavmesh(); NavmeshParams nmconfig = nm.GetConfig(); System.Text.StringBuilder sb = new System.Text.StringBuilder(); sb.AppendLine("Navigation mesh report for " + name); if (mBuildInfo != null) { sb.AppendLine("Built from scene: " + mBuildInfo.inputScene); } sb.AppendLine(string.Format("Tiles: {0}, Tile Size: {1:F3}x{2:F3}, Max Polys Per Tile: {3}" , nmconfig.maxTiles, nmconfig.tileWidth, nmconfig.tileDepth, nmconfig.maxPolysPerTile)); int polyCount = 0; int vertCount = 0; int connCount = 0; for (int i = 0; i < nmconfig.maxTiles; i++) { NavmeshTileHeader header = nm.GetTile(i).GetHeader(); if (header.polyCount == 0) { continue; } sb.AppendLine(string.Format( "Tile ({0},{1}): Polygons: {2}, Vertices: {3}, Off-mesh Connections: {4}" , header.tileX, header.tileZ , header.polyCount, header.vertCount , header.connCount)); polyCount += header.polyCount; vertCount += header.vertCount; connCount += header.connCount; } sb.AppendLine(string.Format( "Totals: Polygons: {0}, Vertices: {1}, Off-mesh Connections: {2}" , polyCount, vertCount, connCount)); return(sb.ToString()); }
public Pathfinder(Navmesh navMesh) { _navMesh = navMesh; _filter = new NavmeshQueryFilter(); if (NavUtil.Failed(NavmeshQuery.Create(_navMesh, 1000, out _query))) { throw new Exception("NavQuery failed"); } _pathCorridor = new PathCorridor(1000, 1000, _query, _filter); }
/// <summary> /// Disable the visualization. /// </summary> public void Hide() { if (mDelegate != null) { SceneView.onSceneGUIDelegate -= mDelegate; SceneView.RepaintAll(); } mNavmeshData = null; mDataVersion = -1; mNavmesh = null; mDelegate = null; }
/// <summary> /// Draws a debug visualization of the specified navigation mesh tile. /// </summary> /// <remarks> /// <para> /// This method is safe to call on empty tile locations. /// </para> /// </remarks> /// <param name="mesh">The mesh.</param> /// <param name="tx">The tile grid x-location.</param> /// <param name="tz">The tile grid z-location.</param> /// <param name="layer">The tile layer.</param> /// <param name="colorByArea"> /// If true, will be colored by polygon area. If false, will be colored by tile index. /// </param> public static void Draw(Navmesh mesh, int tx, int tz, int layer, bool colorByArea) { NavmeshTile tile = mesh.GetTile(tx, tz, layer); if (tile == null) { // No tile at grid location. return; } Draw(tile, null, null, 0 , colorByArea ? -1 : tx.GetHashCode() ^ tz.GetHashCode() ^ layer.GetHashCode()); }
/// <summary> /// Draws a debug visualization of the navigation mesh with the specified polygons /// highlighted. /// </summary> /// <param name="mesh">The mesh to draw.</param> /// <param name="markPolys"> /// The references of the polygons that should be highlighted. /// </param> /// <param name="polyCount"> /// The number of polygons in the <paramref name="markPolys"/> array. /// </param> public static void Draw(Navmesh mesh, uint[] markPolys, int polyCount) { int count = mesh.GetMaxTiles(); for (int i = 0; i < count; i++) { Draw(mesh.GetTile(i) , null , markPolys , polyCount , i); } }
// Use this for initialization void Start() { Rect flappyBoundingRect = SpriteRendererBoundingRect (GameObject.Find ("Flappy").GetComponent<SpriteRenderer> ()); float flappyWidth = 0.5f * flappyBoundingRect.width; float flappyHeight = 0.5f * flappyBoundingRect.height; points = new Navmesh(); float width = Camera.main.pixelWidth; float height = Camera.main.pixelHeight; for (float x = 0; x < width; x += step) { for (float y = 0; y < height; y += step) { Vector3 pointPos = Camera.main.ScreenToWorldPoint(new Vector3(x, y, 0)); // Check at this point, as well as to the left, right, up, down of it to make sure Flappy can fit if (!Physics.Raycast(pointPos, Vector3.forward) && !Physics.Raycast(pointPos + new Vector3(flappyWidth, 0, 0), Vector3.forward) && !Physics.Raycast (pointPos + new Vector3(-flappyWidth, 0, 0), Vector3.forward) && !Physics.Raycast (pointPos + new Vector3(0, flappyHeight, 0), Vector3.forward) && !Physics.Raycast(pointPos + new Vector3(0, -flappyHeight, 0), Vector3.forward)) points.Add(Instantiate(point, pointPos + (10 * Vector3.forward), Quaternion.identity) as GameObject); } } Debug.Log ("Total points: " + points.Count); float gameUnitInPx = (Camera.main.WorldToScreenPoint(new Vector3(1, 0, 0)) - Camera.main.WorldToScreenPoint(new Vector3(0, 0, 0))).x; points.gameUnitStep = (step / gameUnitInPx); if (this.gameObject.GetComponent<AStar_SpecialSourceAndDest> ()) { this.gameObject.GetComponent<AStar_SpecialSourceAndDest> ().UpdateNavmesh (); } }
public void UpdateNavmesh() { navmesh = GameObject.Find ("NavmeshGenerator").GetComponent<NavmeshSpawner> ().GetNavmesh (); }
private void CalculatePath() { //Debug.Log("Calculating..."); navmesh = GameObject.Find("NavmeshGenerator").GetComponent<NavmeshSpawner>().GetNavmesh(); path = new ArrayList(); // cast rays up, down, left, right and if its longer than it should be, ignore the impact float expectedDist = navmesh.gameUnitStep + fudge; // Start the calculation by finding the closest node to the player (or GameObject to which we are attached) GameObject startPoint = FindClosestNavmeshPointTo(this.gameObject); Debug.Log ("Starting from: (" + startPoint.transform.position.x + ", " + startPoint.transform.position.y + ")"); SearchElement startElement = new SearchElement(startPoint, 0.0f); // Then find the closest GameObject to the target endPoint = FindClosestNavmeshPointTo(target.gameObject); //Debug.Log ("Ending at: (" + endPoint.transform.position.x + ", " + endPoint.transform.position.y + ")"); // Keep a priority queue of points on the frontier, sorted in increasing order by F = G + H // The CompareTo() function of each SearchElement takes into account the H value SortedList openSet = new SortedList(); // Keep a list of NavmeshPoints we have already found in the SPT ArrayList closedSet = new ArrayList(); openSet.Add(startElement, null); SearchElement finalSearchElement = null; while (openSet.Count > 0) { // Dequeue the element in the openSet with the smallest distance SearchElement current = openSet.GetKey(0) as SearchElement; // Is this what we are looking for? if (current.point == endPoint) { closedSet.Add(current.point); finalSearchElement = current; break; } // Remove this NavmeshPoint from the openSet and add it to the closedSet openSet.Remove(current); closedSet.Add(current.point); current.point.layer = 9; //Debug.Log ("Processing point at (" + current.point.transform.position.x // + ", " + current.point.transform.position.y + ")"); // Get all NavmeshPoints adjacent to this point in the form of SearchElements whose dists are current.dist // plus however long the edge from current to the adjacent point is (measured in terms of game space dist) ArrayList adj = GetAdjacentPoints(current, expectedDist); // Find out if any points adjacent to current are already in the openSet // If they are, find out if the distance through the current path is shorter than the distance // they are currently at through other paths. If the distance through current is shorter, update the dist // to be the dist through current, and update the from field to be current. // Note: We do not explicitly handle the heuristic estimate at this time, as it is taken care of for us // behind the scenes in the openSet.Add() function by the IComparable interface implemented by SearchElement foreach (SearchElement newFrontierElement in adj) { bool elementInOpenSet = false; bool replaceExistingElement = false; SearchElement existingElementIndex = null; foreach (SearchElement establishedFrontierElement in openSet.Keys) { if (newFrontierElement.point == establishedFrontierElement.point) { // This NavmeshPoint exists in the openSet elementInOpenSet = true; if (newFrontierElement.dist < establishedFrontierElement.dist) { // The new path is a better path than the current path replaceExistingElement = true; existingElementIndex = establishedFrontierElement; } // Break out of the openSet for-loop; we are done here since we found a match break; } } if (!elementInOpenSet) { openSet.Add(newFrontierElement, null); } else if (elementInOpenSet && replaceExistingElement) { openSet.Remove(existingElementIndex); openSet.Add(newFrontierElement, null); } foreach (SearchElement e in openSet.Keys) { //Debug.Log("(" + e.point.transform.position.x + ", " + e.point.transform.position.y + "): " // + (e.dist + Vector2.Distance(e.point.transform.position, endPoint.transform.position)).ToString() // + " "); } } } // We either ran out of elements in the navmesh and should throw an error, or we arrived at the target if (finalSearchElement == null) { throw new Exception("Target element not found by A* algorithm"); } else { // We shouldn't show the close navpoints any longer this.gameObject.GetComponent<ShowNearbyNavpoints>().SendMessage("Cleanup"); // Reconstruct the path that won path = new ArrayList(); pathDist = 0.0f; SearchElement pathPoint = finalSearchElement; while (pathPoint != null) { path.Add(pathPoint.point); pathDist += pathPoint.dist; pathPoint = (SearchElement)pathPoint.from; } // Finally, reverse the path, since we added elements to it in reverse order (i.e. starting from target) path.Reverse(); foreach (GameObject navmeshPoint in path) { SpriteRenderer sr = navmeshPoint.GetComponent<SpriteRenderer>(); sr.enabled = true; sr.color = Color.red; } this.gameObject.GetComponent<FollowPath>().StartFollowing(path); //Debug.Log ("Final path distance: " + pathDist); } }
/// <summary> /// Draws a debug visualization of the specified navigation mesh tile. /// </summary> /// <remarks> /// <para> /// This method is safe to call on empty tile locations. /// </para> /// </remarks> /// <param name="mesh">The mesh.</param> /// <param name="tx">The tile grid x-location.</param> /// <param name="tz">The tile grid z-location.</param> /// <param name="layer">The tile layer.</param> /// <param name="colorByArea"> /// If true, will be colored by polygon area. If false, will be colored by tile index. /// </param> public static void Draw(Navmesh mesh, int tx, int tz, int layer, bool colorByArea) { NavmeshTile tile = mesh.GetTile(tx, tz, layer); if (tile == null) // No tile at grid location. return; Draw(tile, null, null, 0 , colorByArea ? -1 : tx.GetHashCode() ^ tz.GetHashCode() ^ layer.GetHashCode()); }
void OnRenderObject() { if (!mDebugEnabled) return; INavmeshData data = NavmeshData; if (!mNavmeshData || !data.HasNavmesh) { mDebugMesh = null; return; } if (mDebugMesh == null || data.Version != mDebugVersion) { mDebugMesh = data.GetNavmesh(); mDebugVersion = data.Version; if (mDebugMesh == null) return; } NavDebug.Draw(mDebugMesh, false); }
/// <summary> /// Draws a debug visualization of a corridor. /// </summary> /// <param name="mesh">The navigation mesh associated with the corridor.</param> /// <param name="corridor">The corridor to draw.</param> public static void Draw(Navmesh mesh, PathCorridorData corridor) { if (corridor.pathCount == 0) return; DebugDraw.SimpleMaterial.SetPass(0); Vector3[] tileVerts = null; for (int iPoly = 0; iPoly < corridor.pathCount; iPoly++) { NavmeshTile tile; NavmeshPoly poly; mesh.GetTileAndPoly(corridor.path[iPoly], out tile, out poly); if (poly.Type == NavmeshPolyType.OffMeshConnection) continue; NavmeshTileHeader header = tile.GetHeader(); if (tileVerts == null || tileVerts.Length < 3 * header.vertCount) { // Resize. tileVerts = new Vector3[header.vertCount]; } tile.GetVerts(tileVerts); GL.Begin(GL.TRIANGLES); GL.Color(polygonOverlayColor); int pA = poly.indices[0]; for (int i = 2; i < poly.vertCount; i++) { int pB = poly.indices[i - 1]; int pC = poly.indices[i]; GL.Vertex(tileVerts[pA]); GL.Vertex(tileVerts[pB]); GL.Vertex(tileVerts[pC]); } GL.End(); // Not drawing boundaries since it would obscure other agent // debug data. } Vector3 v = corridor.position; DebugDraw.XMarker(v, positionScale, positionColor); DebugDraw.Circle(v, positionScale, positionColor); DebugDraw.Circle(v, positionScale * 0.5f, positionColor); DebugDraw.Circle(v, positionScale * 0.25f, positionColor); v = corridor.target; DebugDraw.XMarker(v, goalScale, goalColor); DebugDraw.Circle(v, goalScale, goalColor); DebugDraw.Circle(v, goalScale * 0.5f, goalColor); DebugDraw.Circle(v, goalScale * 0.25f, goalColor); }
/// <summary> /// Returns the 3D centroids of the provided navigation mesh polygons. /// </summary> /// <remarks> /// <para> /// If a polygon does not exist within the mesh, its associated centroid will not /// be altered. So some centroid data will be invalid if <paramref name="polyCount"/> /// is not equal to the result count. /// </para> /// </remarks> /// <param name="mesh">The navigation mesh containing the polygons.</param> /// <param name="polyRefs">The references of the polygons.</param> /// <param name="polyCount">The number of polygons.</param> /// <param name="centroids"> /// The centroids for the polygons. [Length: >= polyCount] (Out) /// </param> /// <returns>The actual number of polygons found within the mesh. </returns> public static int GetCentroids(Navmesh mesh , uint[] polyRefs , int polyCount , Vector3[] centroids) { int resultCount = 0; int count = mesh.GetMaxTiles(); for (int i = 0; i < count; i++) { resultCount += GetCentroids(mesh.GetTile(i) , polyRefs , polyCount , centroids); if (resultCount == polyRefs.Length) break; } return resultCount; }
public void AttachToNavmesh(Navmesh nav_mesh) { Navmesh = nav_mesh; Navmesh.Navigator.AddListener(this); }
/// <summary> /// Constructor. /// </summary> /// <param name="navmesh">The navigation mesh used by the agents. /// </param> public CrowdAgentDebug(Navmesh navmesh) { this.navmesh = navmesh; }
private void OnSceneGUI(SceneView sceneView) { if (!(ScriptableObject)mNavmeshData) { Hide(); return; } if (!mNavmeshData.HasNavmesh) { mDataVersion = -1; mNavmesh = null; return; } if (mNavmesh == null || mNavmeshData.Version != mDataVersion) { mNavmesh = mNavmeshData.GetNavmesh(); mDataVersion = mNavmeshData.Version; if (mNavmesh == null) return; } NavDebug.Draw(mNavmesh, mColorByArea); }