Skip to content

Instantly share code, notes, and snippets.

@asullivanr
Last active March 31, 2022 17:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save asullivanr/22dea067b7f0544852dda13b62a1bd84 to your computer and use it in GitHub Desktop.
Save asullivanr/22dea067b7f0544852dda13b62a1bd84 to your computer and use it in GitHub Desktop.
Easy point based collider creator using Odin. Add to an Empty GameObject.
using UnityEditor;
using UnityEngine;
using Sirenix.OdinInspector;
namespace TodelmerResources.Scripts.Utilities
{
/// <summary>
/// Creates a group of points that lets you easily create colliders for invisable walls, triggers or general blocking of player movements.
/// </summary>
[ExecuteInEditMode]
[CanEditMultipleObjects]
public class ColliderCreatorOdin : MonoBehaviour
{
#if UNITY_EDITOR
[HideIf("@this.transform.childCount < 1"), Header("Gizmos"), SerializeField]
private bool visualize = true;
[HideIf("@this.transform.childCount < 1"), SerializeField]
private Color gizmosColor = Color.white;
[HideIf("@this.transform.childCount < 1"), Header("Generation"), SerializeField]
private bool generateCapsuleColliders = true;
[HideIf("@this.transform.childCount < 1"), SerializeField]
private bool isTrigger = false;
[HideIf("@this.transform.childCount < 1"), SerializeField]
private bool generateBoxColliders = true;
[HideIf("@this.transform.childCount > 1"), Title("Child objects are not setup."), Button]
private void Setup()
{
if (transform.childCount < 1)
{
var boxContainer = new GameObject("_COLLIDERS");
boxContainer.transform.localPosition = Vector3.zero;
boxContainer.transform.localScale = Vector3.one;
boxContainer.transform.SetParent(this.transform);
var point1 = new GameObject("Point (1)");
point1.transform.SetParent(this.transform);
point1.transform.localPosition = Vector3.zero;
point1.transform.localScale = Vector3.one + Vector3.up * 3;
var point2 = new GameObject("Point (2)");
point2.transform.SetParent(this.transform);
point2.transform.localPosition = Vector3.forward * 5;
point2.transform.localScale = Vector3.one + Vector3.up * 3;
}
}
[HideIf("@this.transform.childCount < 1")]
[ButtonGroup]
private void GenerateColliders()
{
var collidersTransform = this.transform.GetChild(0);
ClearAllColliders();
// create capsule AND box colliders.
for (int i = 1; i < this.transform.childCount; i++)
{
var child = this.transform.GetChild(i);
// create capsule collider.
if (generateCapsuleColliders)
{
var capsuleObject = Instantiate(child, collidersTransform);
var capsuleCollider = capsuleObject.gameObject.AddComponent<CapsuleCollider>();
capsuleCollider.radius = 1;
capsuleCollider.height = 1;
if (isTrigger == true)
{
capsuleCollider.isTrigger = true;
}
}
// create box colliders for inbetween children.
if (generateBoxColliders && i < this.transform.childCount - 1)
{
var nextChild = this.transform.GetChild(i + 1);
var position = (child.position + nextChild.position) / 2f;
var size = new Vector3((child.localScale.x + nextChild.localScale.x) / 2f, (child.localScale.y + nextChild.localScale.y) / 2f, Vector3.Distance(child.position, nextChild.position));
var rotation = Quaternion.LookRotation(nextChild.position - child.position);
var boxChild = new GameObject("Box " + i, typeof(BoxCollider));
boxChild.transform.SetParent(collidersTransform);
boxChild.transform.position = position;
boxChild.transform.localScale = size;
boxChild.transform.rotation = rotation;
if (isTrigger == true)
{
var box = boxChild.GetComponent<BoxCollider>();
box.isTrigger = true;
}
}
}
}
[HideIf("@this.transform.childCount < 1")]
[ButtonGroup]
private void ClearAllColliders()
{
var boxContainerTransform = transform.GetChild(0);
// delete all existing box colliders.
for (int i = boxContainerTransform.childCount - 1; i >= 0; i--)
{
DestroyImmediate(boxContainerTransform.GetChild(i).gameObject);
}
// delete all capsule colliders of children.
for (int i = 1; i < this.transform.childCount; i++)
{
var child = this.transform.GetChild(i);
var capsuleCollider = child.GetComponent<CapsuleCollider>();
if (capsuleCollider != null)
{
DestroyImmediate(capsuleCollider);
}
}
}
private void OnDrawGizmos()
{
if (!visualize)
return;
// start at 1 (2nd child), first child is container for box colliders.
for (int i = 1; i < transform.childCount; i++)
{
var target = transform.GetChild(i);
// render capsule for this child.
if (generateCapsuleColliders)
{
DrawWireCapsule(target.position, target.rotation, target.localScale.x, target.localScale.y);
}
// render box for child inbetween this and next child.
if (generateBoxColliders && i < transform.childCount - 1)
{
var other = transform.GetChild(i + 1);
var position = (target.position + other.position) / 2f;
var size = new Vector3((target.localScale.x + other.localScale.x) / 2f, (target.localScale.y + other.localScale.y) / 2f, Vector3.Distance(target.position, other.position));
Matrix4x4 rotationMatrix = Matrix4x4.TRS(position, Quaternion.LookRotation(other.position - target.position), size);
Gizmos.matrix = rotationMatrix;
Gizmos.color = gizmosColor * 0.3f;
Gizmos.DrawCube(Vector3.zero, Vector3.one);
Gizmos.color = gizmosColor;
Gizmos.DrawWireCube(Vector3.zero, Vector3.one);
Gizmos.matrix = Matrix4x4.identity;
}
}
}
private void DrawWireCapsule(Vector3 position, Quaternion rotation, float radius, float height)
{
Handles.color = gizmosColor;
Matrix4x4 angleMatrix = Matrix4x4.TRS(position, rotation, Handles.matrix.lossyScale);
using (new Handles.DrawingScope(angleMatrix))
{
var pointOffset = (height - (radius * 2)) / 2;
// draw sideways.
Handles.DrawWireArc(Vector3.up * pointOffset, Vector3.left, Vector3.back, -180, radius);
Handles.DrawLine(new Vector3(0, pointOffset, -radius), new Vector3(0, -pointOffset, -radius));
Handles.DrawLine(new Vector3(0, pointOffset, radius), new Vector3(0, -pointOffset, radius));
Handles.DrawWireArc(Vector3.down * pointOffset, Vector3.left, Vector3.back, 180, radius);
// draw frontways.
Handles.DrawWireArc(Vector3.up * pointOffset, Vector3.back, Vector3.left, 180, radius);
Handles.DrawLine(new Vector3(-radius, pointOffset, 0), new Vector3(-radius, -pointOffset, 0));
Handles.DrawLine(new Vector3(radius, pointOffset, 0), new Vector3(radius, -pointOffset, 0));
Handles.DrawWireArc(Vector3.down * pointOffset, Vector3.back, Vector3.left, -180, radius);
// draw center.
Handles.DrawWireDisc(Vector3.up * pointOffset, Vector3.up, radius);
Handles.DrawWireDisc(Vector3.down * pointOffset, Vector3.up, radius);
}
}
#endif
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment