When dealing with regular-size vertices on graph, such as grids, it's pretty common to see some kind of robotic movement from the agents in the game. Depending on the type of game we're developing, this could be avoided using path-smoothing techniques, such as the one we're about to learn.
Let's define a new tag in the Unity editor called Wall
and assign it to every object in the scene that is intended to work as a wall or obstacle in the navigation.
This is an easy, yet powerful, function:
Smooth
function:public List<Vertex> Smooth(List<Vertex> path) { // next steps here }
List<Vertex> newPath = new List<Vertex>(); if (path.Count == 0) return newPath; if (path.Count < 3) return path;
newPath.Add(path[0]); int i, j; for (i = 0; i < path.Count - 1;) { for (j = i + 1; j < path.Count; j++) { // next steps here } i = j - 1; newPath.Add(path[i]); } return newPath;
Vector3 origin = path[i].transform.position; Vector3 destination = path[j].transform.position; Vector3 direction = destination - origin; float distance = direction.magnitude; bool isWall = false; direction.Normalize();
Ray ray = new Ray(origin, direction); RaycastHit[] hits; hits = Physics.RaycastAll(ray, distance);
foreach (RaycastHit hit in hits) { string tag = hit.collider.gameObject.tag; if (tag.Equals("Wall")) { isWall = true; break; } } if (isWall) break;
We create a new path, taking the initial node as a starting point, and apply ray casting to the following node in the path, until we get a collision with a wall. When that happens, we take the previous node as the following node in the new path and the starting point for traversing the original one, until there are no nodes left to check. That way, we build a more intuitive path.