Last active
March 31, 2022 17:34
-
-
Save asullivanr/22dea067b7f0544852dda13b62a1bd84 to your computer and use it in GitHub Desktop.
Easy point based collider creator using Odin. Add to an Empty GameObject.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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