private static void BuildPath <T>(T start, T end, Vec3 from, Vec3 to, NodeInfo info, ref List <path_pos> path) where T : Cell { // build result path if (path != null) { List <Cell> cells_list = new List <Cell>(); while (info != null) { cells_list.Add(info.cell); info = info.parent; } cells_list.Reverse(); for (int i = 0; i < cells_list.Count; ++i) { Cell cell = cells_list[i]; if (i == 0) { if (from.IsEmpty) { path.Add(new path_pos(cell.Center, cell)); } else { path.Add(new path_pos(cell.AABB.Align(from), cell)); } } else { path.Add(new path_pos(cell.AABB.Align(path[path.Count - 1].pos), cell)); } if (i == cells_list.Count - 1) { if (to.IsEmpty) { path.Add(new path_pos(cell.Center, cell)); } else { path.Add(new path_pos(cell.AABB.Align(to), cell)); } } } for (int k = path.Count - 2; k > 0; --k) { path[k] = new path_pos(path[k - 1].cell.AABB.Align(path[k + 1].pos), path[k].cell); } } }
private void SmoothenPath(ref List <path_pos> path, MovementFlag flags, int skip_first_count = 0) { int ray_start_index = skip_first_count; Vec3 intersection = null; while (ray_start_index + 2 < path.Count) { path_pos ray_start_data = path[ray_start_index]; path_pos intermediate_data = path[ray_start_index + 1]; path_pos ray_end_data = path[ray_start_index + 2]; // try remove middle point completely if (m_Navmesh.RayCast2D(ray_start_data.pos, ray_end_data.pos, flags, ref intersection, false)) { path.RemoveAt(ray_start_index + 1); } else { ++ray_start_index; } } // perform second smoothing pass after getting rid of all unnecessary points to get better performance and results // this pass is basically "moving" from point to point and checking at which step (in-between points) I can already see the next point if (PathSmoothingPrecision > 0) { ray_start_index = skip_first_count; while (ray_start_index + 2 < path.Count) { path_pos ray_start_data = path[ray_start_index]; path_pos intermediate_data = path[ray_start_index + 1]; path_pos ray_end_data = path[ray_start_index + 2]; Vec3 dir = intermediate_data.pos - ray_start_data.pos; float length = dir.Normalize(); int steps = (int)(length / PathSmoothingPrecision); for (int i = 1; i < steps; ++i) // checking 0 is unnecessary since this is the current path { if (m_Navmesh.RayCast2D(ray_start_data.pos + dir * (float)i * PathSmoothingPrecision, ray_end_data.pos, flags, ref intersection, false)) { path[ray_start_index + 1] = new path_pos(ray_start_data.pos + dir * (float)i * PathSmoothingPrecision, intermediate_data.cell); break; } } ++ray_start_index; } } }
private void StraightenPath(ref List <path_pos> path, MovementFlag flags, int skip_first_count = 0) { int ray_start_index = skip_first_count; while (ray_start_index + 2 < path.Count) { path_pos ray_start_data = path[ray_start_index]; path_pos intermediate_data = path[ray_start_index + 1]; path_pos ray_end_data = path[ray_start_index + 2]; if (m_Navmesh.RayCast2D(ray_start_data.pos, ray_end_data.pos, flags, false)) { path.RemoveAt(ray_start_index + 1); } else { ++ray_start_index; } } }