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;
}
}
}