/// <summary> /// Provides a standard way detecting where the current /// <see cref="hitPosition"/> is on the navigation mesh. /// </summary> public static SearchResult HandleStandardPolySearch(NavGroup helper , out Vector3 geomPoint , out NavmeshPoint navPoint , out string message) { if (!hasHit) { message = "Outside source geometry."; navPoint = new NavmeshPoint(); geomPoint = Vector3.zero; return(SearchResult.Failed); } geomPoint = hitPosition; NavStatus status = helper.query.GetNearestPoint(geomPoint, helper.extents, helper.filter, out navPoint); message = "GetNearestPoint: " + status.ToString(); if (NavUtil.Failed(status)) { return(SearchResult.HitGeometry); } if (navPoint.polyRef == 0) { message = "Too far from navmesh: GetNearestPoint: " + status.ToString(); return(SearchResult.HitGeometry); } return(SearchResult.HitNavmesh); }
private void CastRay() { NavStatus status = mHelper.query.Raycast(mPosition, mGoal.point , mHelper.filter , out mHitParam, out mHitNorm, mPolyRefs.buffer, out mResultCount); mMessages = "Raycast: " + status.ToString(); }
private void GeneratePath() { NavStatus status = helper.query.FindPath(position, goal , helper.filter, path.buffer , out pathCount); pathID++; mLocalMessage = "FindPath: " + status.ToString(); }
public void Update() { if (mPolyRefs.HandleResize()) { mStraightPath = new Vector3[mPolyRefs.MaxElementCount]; mVisitedCount = 0; mStraightCount = 0; } if (Input.GetKeyDown(StdButtons.SelectA) || Input.GetKey(StdButtons.SelectB)) { Vector3 trasha; string trashb; NavmeshPoint point; QEUtil.SearchResult searchResult = QEUtil.HandleStandardPolySearch(mHelper, out trasha, out point, out trashb); if ((searchResult & QEUtil.SearchResult.HitNavmesh) == 0) { return; } if (mPosition.polyRef == 0 || Input.GetKey(StdButtons.SelectB)) { mPosition = point; mGoal.polyRef = 0; } else { mGoal = point; } mVisitedCount = 0; mStraightCount = 0; } if (mVisitedCount == 0 && mPosition.polyRef != 0 && mGoal.polyRef != 0) { NavStatus status = mHelper.query.MoveAlongSurface(mPosition, mGoal.point , mHelper.filter , out mTarget.point, mPolyRefs.buffer, out mVisitedCount); mMessages = "MoveAlongSurface: " + status.ToString(); if (mVisitedCount > 0) { mHelper.query.GetStraightPath(mPosition.point, mTarget.point , mPolyRefs.buffer, 0, mVisitedCount , mStraightPath , null, null, out mStraightCount); } } }
private uint[] polyResultBuffer = null; //缓存寻路的三角形 public bool loadNavMesh(string fileName) { NavStatus status = loadMeshData(fileName); if ((status & NavStatus.Sucess) == 0) { Debug.LogError(fileName + "Load failed" + status.ToString()); mCrowdManager = null; return(false); } return(true); }
private void GenerateStraightPath() { int iTarget = Mathf.Max(0, mTargetPathIndex); NavStatus status = helper.query.GetStraightPath(mTarget.point, goal.point , path.buffer, iTarget, pathCount - iTarget , mStraightPath.buffer, null, null, out mStraightCount); if (mLocalMessage.Length > 0) { mLocalMessage += ", "; } mLocalMessage = "GetStraightPath: " + status.ToString(); }
public void Update() { // Must set message before returning. mHasPosition = false; mResultCount = 0; mYOffset += QEUtil.GetYFactor(); Vector3 trash; QEUtil.SearchResult result = QEUtil.HandleStandardPolySearch(mHelper, out trash, out mPosition, out mMessage); mHasPosition = (result & QEUtil.SearchResult.HitNavmesh) != 0; if (!mHasPosition) { return; } Vector3 pos = mPosition.point; for (int i = 0; i < mSearchPoly.Length; i++) { mSearchPoly[i] = pos + mBasePoly[i]; mSearchPoly[i].y += mYOffset; } if (mPolyRefs.HandleResize()) { int size = mPolyRefs.MaxElementCount; mParentRefs = new uint[size]; mCosts = new float[size]; mCentroids = new Vector3[size]; } NavStatus status = mHelper.query.FindPolys(mPosition.polyRef, mSearchPoly , mHelper.filter , mPolyRefs.buffer, mParentRefs, mCosts, out mResultCount); mMessage = "FindPolys: " + status.ToString() + "."; if (mResultCount > 0) { NavDebug.GetCentroids(mHelper.mesh, mPolyRefs.buffer, mResultCount, mCentroids); } }
private static bool LoadMesh(CAIBakedNavmesh targ, string filePath) { string msg = null; if (filePath.Length == 0) { return(false); } FileStream fs = null; BinaryFormatter formatter = new BinaryFormatter(); try { fs = new FileStream(filePath, FileMode.Open); System.Object obj = formatter.Deserialize(fs); NavStatus status = targ.Load((byte[])obj, null); if ((status & NavStatus.Sucess) == 0) { msg = status.ToString(); } } catch (System.Exception ex) { msg = ex.Message; } finally { if (fs != null) { fs.Close(); } } if (msg != null) { Debug.LogError(targ.name + ": BakedNavmesh: Load bytes failed: " + msg); return(false); } return(true); }
public void Update() { mHasPosition = false; mResultCount = 0; Vector3 trash; QEUtil.SearchResult result = QEUtil.HandleStandardPolySearch(mHelper, out trash, out mPosition, out mMessage); mHasPosition = (result & QEUtil.SearchResult.HitNavmesh) != 0; if (!mHasPosition) { return; } mYOffset += QEUtil.GetYFactor(); mPosition.point.y += mYOffset; mSearchRadius += QEUtil.GetXZFactor(); if (mPolyRefs.HandleResize()) { int size = mPolyRefs.MaxElementCount; mParentRefs = new uint[size]; mCentroids = new Vector3[size]; } NavStatus status = mHelper.query.GetPolysLocal(mPosition, mSearchRadius , mHelper.filter , mPolyRefs.buffer, mParentRefs, out mResultCount); mMessage = "GetPolysLocal: " + status.ToString() + "."; if (mResultCount > 0) { NavDebug.GetCentroids(mHelper.mesh , mPolyRefs.buffer , mResultCount , mCentroids); } }
public void Update() { float offset = QEUtil.GetXZFactor(); mHelper.extents[0] += offset; mHelper.extents[1] += QEUtil.GetYFactor(); mHelper.extents[2] += offset; mPolyRefs.HandleResize(); mResultCount = 0; mHasPosition = QEUtil.hasHit; if (!mHasPosition) { mMessage = "Outside source geometry."; return; } mHasPosition = true; mPosition = QEUtil.hitPosition; for (int i = 0; i < mPolyRefs.buffer.Length; i++) { mPolyRefs.buffer[i] = 0; } NavStatus status = mHelper.query.GetPolys(mPosition , mHelper.extents, mHelper.filter , mPolyRefs.buffer, out mResultCount); for (int i = 0; i < mResultCount; i++) { if (mPolyRefs.buffer[i] == 0) { Debug.Log("Invalid poly"); } } mMessage = "GetPolys: " + status.ToString(); }
public void Update() { mHasPosition = false; mHasWallHit = false; mWallDistance = 0; mSearchRadius += QEUtil.GetXZFactor(); Vector3 trash; QEUtil.SearchResult result = QEUtil.HandleStandardPolySearch(mHelper, out trash, out mPosition, out mMessage); mHasPosition = (result & QEUtil.SearchResult.HitNavmesh) != 0; if (!mHasPosition) { return; } NavStatus status = mHelper.query.FindDistanceToWall(mPosition, mSearchRadius , mHelper.filter , out mWallDistance, out mWallHitPoint, out mWallNormal); mMessage = "FindDistanceToWall: " + status.ToString() + "."; if ((status & NavStatus.Sucess) == 0) { return; } if (mWallDistance == mSearchRadius) { mMessage += " Nearest wall is outside search radius."; } else { mHasWallHit = true; } }
private NavStatus loadMeshData(string fileName) { Debug.Log("loadMesshDataBegin"); byte[] serializedMesh = readFileByte(fileName); this.fileName = fileName; if (serializedMesh == null) { Debug.Log("serializedMesh == null"); return(NavStatus.Failure | NavStatus.InvalidParam); } // This roundabout method is used for validation. NavStatus status = Navmesh.Create(serializedMesh, out navmesh); if ((status & NavStatus.Sucess) == 0) { Debug.Log("Navmesh.Create Failed"); Debug.Log(status.ToString()); return(status); } //byte[] mDataPack = navmesh.GetSerializedMesh(); //转一遍测试一下 //if (mDataPack == null) //{ // Debug.Log("navmesh.GetSerializedMesh() Failed"); // Debug.Log(mDataPack.ToString()); // return NavStatus.Failure; //} //mBuildInfo = buildConfig; = null; Debug.Log("loadMesshDataSuccess"); return(NavStatus.Sucess); }
public void Update() { mSelectedPoly[0] = 0; mSegmentCount = 0; Vector3 trash; NavmeshPoint pt; QEUtil.SearchResult result = QEUtil.HandleStandardPolySearch(mHelper, out trash, out pt, out mMessage); if ((result & QEUtil.SearchResult.HitNavmesh) == 0) { return; } mSelectedPoly[0] = pt.polyRef; NavStatus status = mHelper.query.GetPolySegments(mSelectedPoly[0] , mHelper.filter , mSegments, mSegmentRefs, out mSegmentCount); mMessage = "GetPolySegments: " + status.ToString(); }
private static Navmesh GenerateNavmesh() { #region Generate Neighboring polygon data //Then generate neighboring polygon data, by parsing the face list MyVector3 <bool> sharedVertex; //For the current face, what vertices are shared with the other face? int sharedVertices; //if goes to 2, edge is shared for (ushort q = 0; q < faces.Count; q++) { //Index of face and neighborPoly refer to the same polygon. neighborPolys.Add(new MyVector3 <ushort>()); neighborPolys[q].x = Navmesh.NullIndex; neighborPolys[q].y = Navmesh.NullIndex; neighborPolys[q].z = Navmesh.NullIndex; //Compare this face with every other face for (ushort w = 0; w < faces.Count; w++) { if (w != q) { sharedVertices = 0; sharedVertex = new MyVector3 <bool>(); //Go from left to right in the face MyVector3 for (int j = 0; j <= 2; j++) { //And compare each index with every other index for (int k = 0; k <= 2; k++) { if (faces[q][j] == faces[w][k]) { //If we find a matching index, update stuff (only for the current face, dont bother with other face, can optimise but will be confusing) sharedVertices++; sharedVertex[j] = true; //could break out of the for loop now, as face will not list the same index twice } } } if (sharedVertices > 2) { ReportError("error: more than 2 vertices shared between polys " + q + " and " + w); } //Check if these faces are sharing an edge if (sharedVertices == 2) { //get the Leftmost Right-To-Left Pair in the neighborPolys MyVector3 //options are: edge 0-1, 1-2, and 2-0, respectively indexing neighboringPolys. (i.e. if index 1 of neighboring polys is 45, that means that the current polygon and polygon 45 share the edge face[1] <-> face[2] if (sharedVertex[0] == true) { if (sharedVertex[1] == true) { neighborPolys[q][0] = w; //I.e. tell this face's MyVector3 of neighboring polygons that the edge made up by vertices at 0 and 1 is shared between polygon q and w } else { neighborPolys[q][2] = w; } } else { neighborPolys[q][1] = w; } } } //End iterating through other faces } } //End iterating through each face #endregion //Now, Load these into Critter AI and create a navmesh navData = new NavmeshTileBuildData(maxPolyVerts, maxPolys, maxVertsPerPoly, 0, 0, 0); #region LoadBase //Get the min and max bounds from the vertex positions float lowest; float highest; //Find the bounds of the mesh. iterate through the x, y and z axes for (int axis = 0; axis <= 2; axis++) { lowest = UPPER_LIMIT; //set to inital values that they do not reach highest = LOWER_LIMIT; //iterate through every vertex to find highest and lowest value of this axis for (int i = 0; i < vertices.Count; i++) { if (vertices[i][axis] < lowest) { lowest = vertices[i][axis]; } if (vertices[i][axis] > highest) { highest = vertices[i][axis]; } } if (axis == 0) //x { boundsMin.x = lowest; boundsMax.x = highest; } else if (axis == 1) { boundsMin.y = lowest; boundsMax.y = highest; } else if (axis == 2) { boundsMin.z = lowest; boundsMax.z = highest; } } bool sucess; sucess = navData.LoadBase(tileX, tileZ, tileLayer, tileUserId, boundsMin, boundsMax, xzCellSize, yCellSize, walkableHeight, walkableRadius, walkableStep, bvTreeEnabled); if (!sucess) { ReportError("Error, LoadBase returned false"); } #endregion #region LoadPolys vertCount = vertices.Count; polyCount = faces.Count; //Convert vertices from world space to grid space polyVerts = new ushort[vertCount * 3]; for (int i = 0; i < vertCount; i++) { polyVerts[3 * i + 0] = (ushort)Math.Round((vertices[i].x - boundsMin.x) / xzCellSize); polyVerts[3 * i + 1] = (ushort)Math.Round((vertices[i].y - boundsMin.y) / yCellSize); polyVerts[3 * i + 2] = (ushort)Math.Round((vertices[i].z - boundsMin.z) / xzCellSize); } //build polys array (http://www.critterai.org/projects/cainav/doc/html/B8C2F0F4.htm) polys = new ushort[6 * polyCount]; int ind = 0; int faceNo = 0; while (faceNo < polyCount) { polys[ind + 0] = faces[faceNo].x; polys[ind + 1] = faces[faceNo].y; polys[ind + 2] = faces[faceNo].z; polys[ind + 3] = neighborPolys[faceNo].x; polys[ind + 4] = neighborPolys[faceNo].y; polys[ind + 5] = neighborPolys[faceNo].z; ind += 6; faceNo++; } //Fill polyflags array with default flags polyFlags = new ushort[polyCount]; for (int i = 0; i < polyCount; i++) { polyFlags[i] = 1; //custom user flag } //Fill polyAreas array polyAreas = new byte[polyCount]; for (int i = 0; i < polyCount; i++) { polyAreas[i] = 1; } sucess = navData.LoadPolys(polyVerts, vertCount, polys, polyFlags, polyAreas, polyCount); if (!sucess) { ReportError("Error, LoadPolys returned false"); } #endregion //Build the Navmesh using the navData NavStatus status = Navmesh.Create(navData, out navmesh); if (status != NavStatus.Sucess) { ReportError("Navmesh build status was " + status.ToString()); } return(navmesh); }
public void Update() { mHasPosition = false; mHasHeight = false; if (Input.GetKeyDown(StdButtons.SelectA)) { Vector3 trash; NavmeshPoint target; QEUtil.SearchResult result = QEUtil.HandleStandardPolySearch(mHelper, out trash, out target, out mMessage); mHasPosition = (result & QEUtil.SearchResult.HitGeometry) != 0; if ((result & QEUtil.SearchResult.HitNavmesh) == 0) { // Could not find polygon. mPolyRef[0] = 0; } else if (target.polyRef == mPolyRef[0]) { // Toggle off the selection. mPolyRef[0] = 0; } else { // New good selection. mPolyRef[0] = target.polyRef; } } if (mPolyRef[0] == 0) { mMessage = "No polygon selected."; return; } RaycastHit hit; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); if (!Physics.Raycast(ray, out hit, 100)) { mMessage = "Outside source geometry."; return; } mPosition.point = hit.point; mHasPosition = true; NavStatus status = mHelper.query.GetPolyHeight( new NavmeshPoint(mPolyRef[0], mPosition.point) , out mHeight); mMessage = "GetPolyHeight: " + status.ToString(); if (NavUtil.Failed(status)) { return; } mHasHeight = true; }
public NavManager CreateManager() { if (!(mNavmeshData && NavmeshData.HasNavmesh)) { Debug.LogError(name + ": Aborted initialization. Navigation mesh not available."); return(null); } if (!mAvoidanceSet || !mGroupsSettings) { Debug.LogError( name + ": Aborted initialization. Avoidance and/or agent groups not available."); return(null); } Navmesh navmesh = NavmeshData.GetNavmesh(); NavmeshQuery query; NavStatus status = NavmeshQuery.Create(navmesh, mMaxQueryNodes, out query); if ((status & NavStatus.Sucess) == 0) { Debug.LogError( name + ": Aborted initialization. Failed query creation: " + status.ToString()); return(null); } CrowdManager crowd = CrowdManager.Create(mMaxCrowdAgents, mMaxAgentRadius, navmesh); if (crowd == null) { Debug.LogError(name + ": Aborted initialization. Failed crowd creation."); return(null); } for (int i = 0; i < CrowdManager.MaxAvoidanceParams; i++) { crowd.SetAvoidanceConfig(i, mAvoidanceSet[i]); } NavGroup mGroup = new NavGroup(navmesh, query, crowd, crowd.QueryFilter, mExtents, false); int count = mGroupsSettings.GroupCount; Dictionary <byte, NavAgentGroup> mAgentGroups = new Dictionary <byte, NavAgentGroup>(count); for (int i = 0; i < count; i++) { byte groupId; NavAgentGroup group = mGroupsSettings.CreateAgentGroup(i, mMaxPath, mMaxStraightPath, out groupId); group.angleAt = mAngleAt; group.heightTolerance = mHeightTolerance; group.radiusAt = mRadiusAt; group.radiusNear = mRadiusNear; group.turnThreshold = mTurnThreshold; mAgentGroups.Add(groupId, group); } return(NavManager.Create(mMaxAgents, mGroup, mAgentGroups)); }
public NavManager CreateManager() { CheckCrowdAvoidanceSet(); if (!(mNavmeshData && NavmeshData.HasNavmesh)) { Debug.LogError("Aborted initialization. Navigation mesh not available."); return(null); } //Debug.Log("NavmeshData-------"+ NavmeshData); Navmesh navmesh = NavmeshData.GetNavmesh(); if (navmesh == null) { NavStatus theStatus = Navmesh.Create(navMeshData, out navmesh); Debug.Log("Navmesh.Create ---->" + theStatus + "---->" + (int)(theStatus & NavStatus.Sucess)); if (NavUtil.Failed(theStatus)) { Debug.LogError("NavUtil.Failed(Navmesh.Create(navMeshData, out navmesh) Fail!"); } Debug.Log("--------------------\n" + navMeshData + "---" + navMeshData.Length + "\n-----------------\nNavmesh-------" + navmesh); } if (navmesh == null) { Debug.LogError(" navmesh is null"); return(null); } NavmeshQuery query; NavStatus status = NavmeshQuery.Create(navmesh, mMaxQueryNodes, out query); if ((status & NavStatus.Sucess) == 0) { Debug.LogError(" Aborted initialization. Failed query creation: " + status.ToString()); return(null); } CrowdManager crowd = CrowdManager.Create(mMaxCrowdAgents, mMaxAgentRadius, navmesh); if (crowd == null) { Debug.LogError("Aborted initialization. Failed crowd creation."); return(null); } for (int i = 0; i < CrowdManager.MaxAvoidanceParams; i++) { crowd.SetAvoidanceConfig(i, CrowdAvoidanceConfig[i]); } NavGroup mGroup = new NavGroup(navmesh, query, crowd, crowd.QueryFilter, mExtents, false); int count = AgentGroupSettingManager.GetGroupCount(); Dictionary <byte, NavAgentGroups> mAgentGroups = new Dictionary <byte, NavAgentGroups>(count); for (int i = 0; i < count; i++) { byte groupId; NavAgentGroups group = AgentGroupSettingManager.CreateAgentGroup(i, mMaxPath, mMaxStraightPath, out groupId); group.angleAt = mAngleAt; group.heightTolerance = mHeightTolerance; group.turnThreshold = mTurnThreshold; mAgentGroups.Add(groupId, group); } return(NavManager.Create(mMaxAgents, mGroup, mAgentGroups)); }
public void CreateQuery(float fMoveSpeed, float fTurnSpeed) { this.mTurnSpeed = fTurnSpeed; this.mMoveSpeed = fMoveSpeed; NavStatus status = NavmeshQuery.Create(navmesh, mMaxQueryNodes, out query); if ((status & NavStatus.Sucess) == 0) { Debug.LogError( fileName + ": Aborted initialization. Failed query creation: " + status.ToString()); mCrowdManager = null; return; } mCrowdManager = CrowdManager.Create(mMaxCrowdAgents, mMaxAgentRadius, navmesh); if (mCrowdManager == null) { Debug.LogError(fileName + ": Aborted initialization. Failed crowd creation."); } CrowdAvoidanceParams mCrowdParam = CrowdAvoidanceParams.CreateStandardMedium(); mCrowdManager.SetAvoidanceConfig(0, mCrowdParam); mCrowdAgentParams = new CrowdAgentParams(); mCrowdAgentParams.avoidanceType = 0; mCrowdAgentParams.collisionQueryRange = 3.2f; mCrowdAgentParams.height = 1.8f; mCrowdAgentParams.maxAcceleration = 8.0f; mCrowdAgentParams.maxSpeed = this.mMoveSpeed; mCrowdAgentParams.pathOptimizationRange = 12.0f; mCrowdAgentParams.radius = 1.0f; mCrowdAgentParams.separationWeight = 2.0f; mCrowdAgentParams.updateFlags = CrowdUpdateFlags.AnticipateTurns | CrowdUpdateFlags.ObstacleAvoidance | CrowdUpdateFlags.CrowdSeparation | CrowdUpdateFlags.OptimizeVis | CrowdUpdateFlags.OptimizeTopo; polyResult = new uint[300]; pointResult = new Vector3[300]; tileBufferPoints = new Vector3[3000]; pointResultBuffer = new Vector3[300]; polyResultBuffer = new uint[300]; NavmeshTile tile = navmesh.GetTile(0); int count = tile.GetVerts(tileBufferPoints); Debug.Log("Tile " + tile.GetTileRef() + " count:" + count); if (count > 3000) { tileBufferPoints = new Vector3[count]; } tileBufferRef = -1; //NavmeshPoly[] polys=new NavmeshPoly[3000]; //int polyCount; //polyCount=tile.GetPolys(polys); //for (int i = 0; i < polyCount; i++) //{ // NavmeshPoly poly = polys[i]; // //if (poly.Type == NavmeshPolyType.OffMeshConnection) // { // Debug.Log("Poly" + i+"type"+poly.Type.ToString()); // } //} }