Unity自动生成阻挡Collider的GameObject工具

Posted 丁小未

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity自动生成阻挡Collider的GameObject工具相关的知识,希望对你有一定的参考价值。

前言

场景中会有碰撞阻挡,或者触发器,一般是美术或者策划配置,策划一般是直接配置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

更多精品教程

http://dingxiaowei.cn/

以上是关于Unity自动生成阻挡Collider的GameObject工具的主要内容,如果未能解决你的问题,请参考以下文章

Unity使用Polygon Collider 2D 实现不规则图形碰撞自动匹配

Unity入门计划基本概念-2D碰撞体Collider 2D

Unity 3D 碰撞体(Collider)|| Unity 3D 触发器(Trigger)

Unity3d中 OnTriggerEnter(Collider other) 和OnCollisionEnter(Collision other)对比

Unity:Collider.bounds.extends.x 自最新更新以来返回半径 - 为啥?

Unity -- Collider(碰撞器与触发器)