using System.Collections.Generic; using System.Linq; using UnityEngine; // ReSharper disable ForCanBeConvertedToForeach namespace DestroyIt { public static class GameObjectExtensions { /// Removes all components of type T from the game object and its children. public static void RemoveAllFromChildren(this GameObject obj) where T : Component { if (obj == null) return; foreach (T comp in obj.GetComponentsInChildren()) Object.Destroy(comp); } public static void RemoveComponent(this GameObject obj) where T : Component { if (obj == null) return; T component = obj.GetComponent(); if (component != null) Object.Destroy(component); } public static List GetComponentsInChildrenOnly(this GameObject obj) where T : Component { return GetComponentsInChildrenOnly(obj, false); } public static List GetComponentsInChildrenOnly(this GameObject obj, bool includeInactive) where T : Component { var components = obj.GetComponentsInChildren(includeInactive).ToList(); components.Remove(obj.GetComponent()); return components; } /// Be sure to set SolverIterationCount to around 25-30 in your Project Settings in order to get solid joints. public static void AddStiffJoint(this GameObject go, Rigidbody connectedBody, Vector3 anchorPosition, Vector3 axis, float breakForce, float breakTorque) { FixedJoint joint = go.AddComponent(); joint.anchor = anchorPosition; joint.connectedBody = connectedBody; joint.breakForce = breakForce; joint.breakTorque = breakTorque; } /// Attempts to get the center point location of a game object's combined meshes. /// If your gameobject has multiple meshes under it which together make up a car (wheels, body, etc), this function will attempt to find /// the centerpoint of the car, taking into account all of the child meshes. /// The gameobject parent containing the meshes. /// Pass in the collection of mesh renderers on this game object (including children) to save on performance. /// The centerpoint location of the gameobject's meshes. public static Vector3 GetMeshCenterPoint(this GameObject go, MeshRenderer[] meshRenderers = null) { // first, get all the mesh renderers on the game object and children if they are not provided if (meshRenderers == null) meshRenderers = go.GetComponentsInChildren(); // if there are no mesh renderers, return a zero vector (the gameobject's pivot position). if (meshRenderers.Length == 0) return Vector3.zero; // if any mesh renderer on this game object is marked as Static, return a zero vector (the gameobject's pivot position) instead // of trying to get the bounding boxes of static meshes. if (go.IsAnyMeshPartOfStaticBatch(meshRenderers)) return Vector3.zero; // if we made it this far, calculate the center point of the combined mesh bounds for the object and use that. Bounds combinedBounds = new Bounds(); MeshFilter[] meshFilters = go.GetComponentsInChildren(); foreach (MeshFilter meshFilter in meshFilters) { Mesh sharedMesh = meshFilter.sharedMesh; if (sharedMesh != null) // some meshFilters do not have shared meshes. combinedBounds.Encapsulate(sharedMesh.bounds); } return combinedBounds.center; } public static bool IsAnyMeshPartOfStaticBatch(this GameObject go, MeshRenderer[] meshRenderers = null) { // first, get all the mesh renderers on the game object and children if they are not provided if (meshRenderers == null) meshRenderers = go.GetComponentsInChildren(); // if there are no mesh renderers, return false. if (meshRenderers.Length == 0) return false; // if any mesh renderer on this game object is marked as Static, return true. for (int i = 0; i < meshRenderers.Length; i++) { if (meshRenderers[i].isPartOfStaticBatch) return true; } return false; } } }