|
// ---------------------------------------------------------------------------- |
|
// Author: Simon Andersen |
|
// Date: 2/11/2020 |
|
// ---------------------------------------------------------------------------- |
|
// |
|
// Attach this component to a gameobject with either an Edge/Circle/CapsuleCollider2D or a CompositeCollider2D and this |
|
// will automatically generate a child collider with a geometry that is an exact copy of the geometry of this collider. |
|
// |
|
// -- Note on the CompositeCollider2D: |
|
// Any Box/Polygon/TilemapCollider2D can be used by a CompositeCollider2D, meaning that with this utility we can |
|
// generate any collider composed of a combination of one or more Box/Polygon/TilemapCollider2D. A CompositeCollider2D |
|
// always requires to attach a Rigidbody2D to the gameobject but remember you can always set the body type of the |
|
// RigidBody as static if you don't need it for anything else. |
|
|
|
#if UNITY_EDITOR |
|
using System.Linq; |
|
using UnityEditor; |
|
using UnityEngine; |
|
|
|
[ExecuteInEditMode] |
|
public class GenerateCollider : MonoBehaviour |
|
{ |
|
[Tooltip("When activated, the child collider will be re-generated everytime this gameobject is modified while in " + |
|
"edit mode. If this is slow, disable this and use the Generate button manually.")] |
|
public bool automaticGeneration; |
|
|
|
private GameObject _child; |
|
private CompositeCollider2D _compositeCollider; |
|
private EdgeCollider2D _edgeCollider; |
|
private CircleCollider2D _circleCollider; |
|
private CapsuleCollider2D _capsuleCollider; |
|
|
|
private void Update() |
|
{ |
|
if (!automaticGeneration || Application.isPlaying || Selection.activeGameObject != gameObject) return; |
|
Generate(); |
|
} |
|
|
|
public void Generate() |
|
{ |
|
// Cleanup previous generated colliders before generating |
|
const string childName = "GeneratedCollider"; |
|
(from Transform child in transform select child.gameObject).ToList().ForEach(child => |
|
{ |
|
if (child.name.Contains(childName)) |
|
DestroyImmediate(child); |
|
}); |
|
|
|
_compositeCollider = GetComponent<CompositeCollider2D>(); |
|
_edgeCollider = GetComponent<EdgeCollider2D>(); |
|
_circleCollider = GetComponent<CircleCollider2D>(); |
|
_capsuleCollider = GetComponent<CapsuleCollider2D>(); |
|
|
|
_child = new GameObject(childName); |
|
_child.transform.SetParent(transform, worldPositionStays:false); |
|
|
|
if (_edgeCollider != null) |
|
GenerateEdgeCollider(); |
|
else if (_circleCollider != null) |
|
GenerateCircleCollider(); |
|
else if (_capsuleCollider != null) |
|
GenerateCapsuleCollider(); |
|
else |
|
GeneratePolygonCollider(); |
|
} |
|
|
|
#region Per Collider type generate function |
|
private void GenerateEdgeCollider() |
|
{ |
|
var childCollider = _child.AddComponent<EdgeCollider2D>(); |
|
childCollider.SetPoints(_edgeCollider.points.ToList()); |
|
childCollider.offset = _edgeCollider.offset; |
|
childCollider.edgeRadius = _edgeCollider.edgeRadius; |
|
} |
|
|
|
private void GenerateCircleCollider() |
|
{ |
|
var childCollider = _child.AddComponent<CircleCollider2D>(); |
|
childCollider.radius = _circleCollider.radius; |
|
childCollider.offset = _circleCollider.offset; |
|
} |
|
|
|
private void GenerateCapsuleCollider() |
|
{ |
|
var childCollider = _child.AddComponent<CapsuleCollider2D>(); |
|
childCollider.size = _capsuleCollider.size; |
|
childCollider.offset = _capsuleCollider.offset; |
|
childCollider.direction = _capsuleCollider.direction; |
|
} |
|
|
|
// This is used for any combination of one or more Box/Polygon/TilemapCollider2D with a CompositeCollider2D |
|
private void GeneratePolygonCollider() |
|
{ |
|
var childCollider = _child.AddComponent<PolygonCollider2D>(); |
|
childCollider.pathCount = 0; |
|
|
|
foreach (var i in Enumerable.Range(0, _compositeCollider.pathCount)) |
|
{ |
|
var points = new Vector2[_compositeCollider.GetPathPointCount(i)]; |
|
_compositeCollider.GetPath(i, points); |
|
childCollider.pathCount++; |
|
childCollider.SetPath(i, points); |
|
} |
|
} |
|
#endregion |
|
} |
|
|
|
#region Custom Editor |
|
[CustomEditor(typeof(GenerateCollider))] |
|
public class GenerateColliderEditor : Editor |
|
{ |
|
public override void OnInspectorGUI() |
|
{ |
|
DrawDefaultInspector(); |
|
var baseScript = (GenerateCollider)target; |
|
if (GUILayout.Button(nameof(baseScript.Generate))) |
|
baseScript.Generate(); |
|
} |
|
} |
|
#endregion |
|
#endif |