Finally, here is a collection of small(ish) utility functions. None of them warrants a separate post. As usual, you can find this, and more, on my Bitbucket Repository.
First, since Transform.Find() only iterates over the direct children of a Transform, here are two functions to find objects in a hierarchy as DFS and BFS:
//Breadth-first search public static Transform FindBroad(this Transform aParent, string aName) { var result = aParent.Find(aName); if (result != null) return result; foreach (Transform child in aParent) result = child.FindBroad(aName); if (result != null) return result; } return null; } //Depth-first search public static Transform FindDeep(this Transform aParent, string aName) { foreach (Transform child in aParent) { if (child.name == aName) return child; var result = child.FindDeep(aName); if (result != null) return result; } return null; }
If you need the Canvas object for an UI element, you can use this:
public static Canvas GetCanvas(this Transform obj) { Canvas canvas = obj.GetComponent<Canvas>(); while (canvas == null && obj.parent != null) { obj = obj.parent; canvas = obj.GetComponent<Canvas>(); } return canvas; }
This is a small function to copy the values from one Transform to another:
public static void Set(this Transform destination, Transform source, Space space = Space.Self) { if (space == Space.Self) { destination.localPosition = source.localPosition; destination.localRotation = source.localRotation; } else { destination.position = source.position; destination.rotation = source.rotation; } destination.localScale = source.localScale; }
Here is a function that calculates a random direction vector within a cone around an initial direction. I use it, for example, to controll the spread of a gun.
public static Vector3 RandomInCone(this Vector3 dir, float openingAngle) { Vector3 deviation = Random.insideUnitSphere; dir = dir.normalized; deviation -= Vector3.Dot(deviation, dir) * dir; return (dir * Mathf.Cos(openingAngle) + deviation * Mathf.Sin(openingAngle)).normalized; }
This here might be a bit niched, but it calculates the angle between a vector and the horizontal plane.
public static float Theta(this Vector3 vector) { float y = vector.y; float x = Mathf.Sqrt(vector.x*vector.x + vector.z*vector.z); return Mathf.Atan2(y, x); }
Lastly, here are two functions to calculate the length and the cost of a NavMeshPath (since Unity doesn’t provide a way to get these, yet). The cost-function can sometimes break at NavMesh borders.
public static float Length(this NavMeshPath path) { if (path.corners.Length < 2) return 0; float length = 0; for (int i = 1; i < path.corners.Length; ++i) { length += Vector3.Distance(path.corners[i], path.corners[i - 1]); } return length; } public static float Cost(this NavMeshPath path) { if (path.corners.Length < 2) return 0; float cost = 0; NavMeshHit hit; NavMesh.SamplePosition(path.corners[0], out hit, 0.1f, NavMesh.AllAreas); Vector3 rayStart = path.corners[0]; int mask = hit.mask; int index = IndexFromMask(mask); for (int i = 1; i < path.corners.Length; ++i) { while (true) { NavMesh.Raycast(rayStart, path.corners[i], out hit, mask); cost += NavMesh.GetAreaCost(index) * hit.distance; if (hit.mask != 0) mask = hit.mask; index = IndexFromMask(mask); rayStart = hit.position; if (hit.mask == 0) { rayStart += (path.corners[i] - rayStart).normalized * 0.01f; } if (!hit.hit) break; } } return cost; }
Comments