UnityTools
UnityTools copied to clipboard
Updatable CylinderCollider in runtime
I have modified the CylinderCollider and CylinderColliderEditor classes to update on run time.
using UnityEngine;
using System.Collections;
namespace kode80.Colliders
{
public class CylinderCollider : MonoBehaviour
{
public float radius = 0.5f;
public float height = 1.0f;
[Range( 4, 64)]
public int boxCount = 5;
[Range( 0.1f, 3.0f)]
public float widthScale = 1.0f;
public bool capTop;
public bool capBottom;
[Space]
public bool alwaysDrawGizmo;
[Space]
public bool isTrigger;
public PhysicMaterial material;
public Transform colliderParent;
public bool hasBaked;
void Awake ()
{
CreateOrUpdateColliders();
//enabled = false;
}
// Update is called once per frame
void Update () {
}
void OnDrawGizmos()
{
Gizmos.color = Color.grey;
OnDrawGizmosSelected();
}
void OnDrawGizmosSelected()
{
if( Application.isPlaying || enabled == false) { return; }
float radiusStep = CalculateRotationStep();
float rotationY = 0.0f;
Vector3 boxSize = CalculateBoxSize();
for( int i=0; i<boxCount; i++)
{
var oldMatrix = Gizmos.matrix;
var newMatrix = Matrix4x4.TRS( Vector3.zero, Quaternion.Euler( 0.0f, rotationY, 0.0f), Vector3.one);
Gizmos.matrix = transform.localToWorldMatrix * newMatrix;
Gizmos.DrawWireCube( Vector3.zero, boxSize);
Gizmos.matrix = oldMatrix;
rotationY += radiusStep;
}
Vector3 capOffset = new Vector3( 0.0f, height * 0.5f, 0.0f);
if( capBottom)
{
var oldMatrix = Gizmos.matrix;
var newMatrix = Matrix4x4.TRS( capOffset * -1.0f, Quaternion.identity, Vector3.one);
Gizmos.matrix = transform.localToWorldMatrix * newMatrix;
Gizmos.DrawWireSphere( Vector3.zero, radius);
Gizmos.matrix = oldMatrix;
}
if( capTop)
{
var oldMatrix = Gizmos.matrix;
var newMatrix = Matrix4x4.TRS( capOffset, Quaternion.identity, Vector3.one);
Gizmos.matrix = transform.localToWorldMatrix * newMatrix;
Gizmos.DrawWireSphere( Vector3.zero, radius);
Gizmos.matrix = oldMatrix;
}
}
public void CreateColliders( Transform parent)
{
Vector3 boxSize = CalculateBoxSize();
float radiusStep = CalculateRotationStep();
Transform colliderTransform;
for( int i=0; i<boxCount; i++) {
colliderTransform = CreateBoxCollider( i, boxSize, radiusStep * i).transform;
colliderTransform.SetParent( transform, false);
colliderTransform.SetParent( parent, true);
}
if( capTop) {
colliderTransform = CreateCapCollider( true).transform;
colliderTransform.SetParent( transform, false);
colliderTransform.SetParent( parent, true);
}
if( capBottom) {
colliderTransform = CreateCapCollider( false).transform;
colliderTransform.SetParent( transform, false);
colliderTransform.SetParent( parent, true);
}
}
private BoxCollider CreateBoxCollider( int index, Vector3 size, float rotationY)
{
var collider = new GameObject( "Cylinder_Box_" + index).AddComponent<BoxCollider>();
collider.size = size;
collider.transform.localRotation = Quaternion.Euler( 0.0f, rotationY, 0.0f);
collider.isTrigger = isTrigger;
collider.material = material;
return collider;
}
private SphereCollider CreateCapCollider( bool isTop)
{
var collider = new GameObject( "Cylinder_Cap_" + (isTop ? "Top" : "Bottom")).AddComponent<SphereCollider>();
collider.radius = radius;
collider.center = new Vector3( 0.0f, height * (isTop ? 0.5f : -0.5f), 0.0f);
collider.isTrigger = isTrigger;
collider.material = material;
return collider;
}
private Vector3 CalculateBoxSize()
{
float circumference = radius * 2.0f * Mathf.PI;
float width = circumference / boxCount;
width = radius / boxCount * 2.0f * widthScale;
return new Vector3( width, height, radius * 2.0f);
}
private float CalculateRotationStep()
{
return 360.0f / boxCount;
}
/*
Methods bellow created by MrAngalo
*/
public void CreateOrUpdateColliders()
{
if (!hasBaked)
{
CreateColliders(colliderParent == null ? transform : colliderParent);
hasBaked = true;
}
else
{
UpdateColliders();
}
}
public void UpdateColliders()
{
Vector3 boxSize = CalculateBoxSize();
float radiusStep = CalculateRotationStep();
Transform colliderTransform;
for (int i = 0; i < boxCount; i++)
{
colliderTransform = UpdateBoxCollider(i, boxSize, radiusStep * i).transform;
}
if (capTop)
{
colliderTransform = UpdateCapCollider(true).transform;
}
if (capBottom)
{
colliderTransform = UpdateCapCollider(false).transform;
}
}
private BoxCollider UpdateBoxCollider(int index, Vector3 size, float rotationY)
{
var collider = transform.Find("Cylinder_Box_" + index).GetComponent<BoxCollider>();
collider.size = size;
collider.transform.localRotation = Quaternion.Euler(0.0f, rotationY, 0.0f);
collider.isTrigger = isTrigger;
collider.material = material;
return collider;
}
private SphereCollider UpdateCapCollider(bool isTop)
{
var collider = transform.Find("Cylinder_Cap_" + (isTop ? "Top" : "Bottom")).GetComponent<SphereCollider>();
collider.radius = radius;
collider.center = new Vector3(0.0f, height * (isTop ? 0.5f : -0.5f), 0.0f);
collider.isTrigger = isTrigger;
collider.material = material;
return collider;
}
}
}
using UnityEngine;
using UnityEditor;
using System.Collections;
namespace kode80.Colliders
{
[CustomEditor( typeof(CylinderCollider))]
public class CylinderColliderEditor : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
var cylinder = target as CylinderCollider;
if(GUILayout.Button( "Bake or Update Colliders"))
{
cylinder.CreateOrUpdateColliders();
//cylinder.enabled = false;
}
}
}
}