Community Made Tools

Have you made any useful utilities with Odin?

Login and submit your creations here

Easy point based collider creator using Odin

Authored by Andrew
Shared 07-04-2022

This is a simple GameObject based collider creator.

Add the script to an empty GameObject then using its children to place points the script will then generate a collider based on the provided child objects.

Gist version is easier and faster to modify, so use it as it may have newer version than here

ColliderCreatorOdin.cs

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