前言
场景中会有碰撞阻挡,或者触发器,一般是美术或者策划配置,策划一般是直接配置collider,但为了调试方便,需要显示对应的mesh方便查看防止的位置是否正确,我们可以写个工具来控制生成mesh和删除mesh方便调试使用。
思路
一般就是几种内置的collider,meshcollider、boxcollider、capsulecollider、spherecollider等,我们判断出对应的collider,然后创建unity内置的一些GameObject即可,meshcollider只需要实例化collider的mesh即可。
效果
代码
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using Sirenix.Utilities.Editor;
using Sirenix.OdinInspector;
using System;
public class ColliderMeshGenerateTool : MonoBehaviour
{
bool show = false;
List<GameObject> mColliderObjCache = new List<GameObject>();
List<GameObject> mGameObjects = new List<GameObject>();
[ShowInInspector]
public bool Show
{
get
{
return show;
}
set
{
ChangeState(value);
show = value;
}
}
void Start()
{
mGameObjects = GetAllSceneObjectsWithInactive();
}
private void ChangeState(bool isShow)
{
if (isShow)
{
foreach (var obj in mGameObjects)
{
if (obj.GetComponent<MeshRenderer>() == null)
AnalyzeCollider(obj);
}
}
else
{
for (int i = mColliderObjCache.Count - 1; i >= 0; i--)
{
GameObject.DestroyImmediate(mColliderObjCache[i]);
}
mColliderObjCache.Clear();
}
}
private void AnalyzeCollider(GameObject obj)
{
var collider = obj.GetComponent<Collider>();
if (collider == null)
{
Debug.LogError("不存在Collider");
return;
}
Type type = collider.GetType();
GameObject tempObj = null;
if (type == typeof(SphereCollider))
{
tempObj = CreatePrimitiveGameObject(obj.transform, PrimitiveType.Sphere);
var sphereCollider = obj.GetComponent<SphereCollider>();
tempObj.transform.localScale = sphereCollider.radius * Vector3.one * 2;
}
else if (type == typeof(BoxCollider))
{
tempObj = CreatePrimitiveGameObject(obj.transform, PrimitiveType.Cube);
var boxCollider = obj.GetComponent<BoxCollider>();
tempObj.transform.localScale = boxCollider.size;
}
else if (type == typeof(MeshCollider))
{
tempObj = CreateGameObject(obj.transform, "MeshGameObject");
tempObj.AddComponent<MeshRenderer>();
var filter = tempObj.AddComponent<MeshFilter>();
var meshCollider = obj.GetComponent<MeshCollider>();
filter.mesh = meshCollider.sharedMesh;
}
else if (type == typeof(CapsuleCollider))
{
tempObj = CreatePrimitiveGameObject(obj.transform, PrimitiveType.Capsule);
var capsuleCollider = obj.GetComponent<CapsuleCollider>();
var doubleRadius = capsuleCollider.radius * 2;
var tempScaleY = capsuleCollider.height < capsuleCollider.radius * 2 ? capsuleCollider.radius : capsuleCollider.height / 2;
tempObj.transform.localScale = new Vector3(doubleRadius, tempScaleY, doubleRadius);
}
if (tempObj != null)
mColliderObjCache.Add(tempObj);
}
private GameObject CreatePrimitiveGameObject(Transform parent, PrimitiveType type = PrimitiveType.Cube)
{
var obj = GameObject.CreatePrimitive(type);
obj.transform.parent = parent;
ResetTransformData(obj);
return obj;
}
private GameObject CreateGameObject(Transform parent, string name)
{
var obj = new GameObject(name);
obj.transform.parent = parent;
ResetTransformData(obj);
return obj;
}
private void ResetTransformData(GameObject obj)
{
obj.transform.localPosition = Vector3.zero;
obj.transform.localRotation = Quaternion.Euler(Vector3.zero);
obj.transform.localScale = Vector3.one;
}
/// <summary>
/// Select All ActiveInHierarchy GameObject in Hierarchy
/// </summary>
/// <returns></returns>
private List<GameObject> GetAllSceneObjectsWithInactive()
{
var allTransforms = Resources.FindObjectsOfTypeAll(typeof(Transform));
var previousSelection = Selection.objects;
Selection.objects = allTransforms.Cast<Transform>()
.Where(x => x != null)
.Select(x => x.gameObject)
.Where(x => x != null && x.activeInHierarchy)
.Where(x => x.GetComponent<Collider>() != null)
.Cast<UnityEngine.Object>().ToArray();
var selectedTransforms = Selection.GetTransforms(SelectionMode.Editable | SelectionMode.ExcludePrefab);
Selection.objects = previousSelection;
return selectedTransforms.Select(tr => tr.gameObject).ToList();
}
}
#endif