编辑器扩展(控制某场景同一类型(所有挂载同一脚本)的物体)

2019-06-01  本文已影响0人  UnityChan

显示和隐藏某场景下所有用来做触发检测的物体

我们在日常的游戏项目开发的过程中,碰撞和触发检测是不可避免的,一般设置好触发Trigger的物体后,我们就会把它的Mesh Renderer组件设置为false。如果项目做大了,突然需要更改某个Trigger的形状或者要取消某个Trigger,那就要从Hierarchy窗口一个一个慢慢找,因为Mesh Renderer设置为false的物体在Scene窗口是无法被鼠标选中,而且完全看不见你也点击不到啊(hhh...),废话不多说,步入正题吧.

这是所有要用到检测触发的父类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class InteractObj : MonoBehaviour
{
    protected virtual void OnTriggerEnter(Collider collider)
    {

    }

    protected virtual void OnTriggerExit(Collider collider)
    {

    }

#if UNITY_EDITOR

    [Header("Editor")]

    public MeshRenderer MeshRenderer;

    public void MeshRendererNull()
    {
        MeshRenderer = null;
    }

    public void MeshRendererGet()
    {
        if (MeshRenderer == null)
        {
            MeshRenderer = GetComponent<MeshRenderer>();
        }
    }

    public void ShowView()
    {
        if (MeshRenderer != null)
            MeshRenderer.enabled = true;
    }

    public void HideView()
    {
        if (MeshRenderer != null)
            MeshRenderer.enabled = false;
    }
#endif

}

我们在写自己的触发脚本时,都让它们继承InteractObj ,不用再继承Mono
类似于这样就可以了

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestAAA : InteractObj {

    protected override void OnTriggerEnter(Collider collider)
    {
        base.OnTriggerEnter(collider);
    }
    protected override void OnTriggerExit(Collider collider)
    {
        base.OnTriggerExit(collider);
    }

}

好了,最后就是我们的编辑器扩展类了

本类用于开启和隐藏所有继承于InteractObj类的所有脚本

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEngine.SceneManagement;

public class ShowAndHideObj 
{
    [MenuItem("Tools/_Interact/Show_Collider_View")]
    static void ShowView()
    {
        List<InteractObj> interactObjs = GetCurrentActiveSceneTypeObjs<InteractObj>();
        if (interactObjs.Count>0)
        {
            interactObjs.ForEach(x => x.ShowView());
            Scene scene = SceneManager.GetSceneByName(interactObjs[0].gameObject.scene.name);
            UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene);
        }
    }

    [MenuItem("Tools/_Interact/Hide_Collider_View")]
    static void HideView()
    {
        List<InteractObj> interactObjs = GetCurrentActiveSceneTypeObjs<InteractObj>();

        if (interactObjs.Count > 0)
        {
            interactObjs.ForEach(x => x.HideView());
            Scene scene = SceneManager.GetSceneByName(interactObjs[0].gameObject.scene.name);
            UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene);
        }
    }

    /// <summary>
    /// 此方法用来得到某场景下所有物体,查出所有挂载T类型的脚本
    /// </summary>
    public static List<T> GetCurrentActiveSceneTypeObjs<T>(bool includeInactive = false) where T : MonoBehaviour
    {
        List<T> objs = new List<T>();
        objs.Clear();
        GameObject[] rootGameObjects = getSceneRootGameObjects(GetCurrentActiveScene());
        for (int i = 0; i < rootGameObjects.Length; i++)
        {           
            T[] objsTyps = rootGameObjects[i].transform.GetComponentsInChildren<T>(false);
            objs.AddRange(objsTyps);
        }
        objs.RemoveAll(x => x == null);
        return objs;
    }

    public static GameObject[] getSceneRootGameObjects(Scene scene)
    {
        return scene.GetRootGameObjects();
    }
    public static Scene GetCurrentActiveScene()
    {
        return SceneManager.GetActiveScene();
    }
}

上诉脚本便可实现开启和关闭某场景下所有继承InteractObj类的物体啦。

在这里做一点补充

在上面脚本有用到GetComponentsInChildren<T>(bool);
GetComponentsInChildren是用来得到自己和它的孩子有同样的T类型组件
在这里 bool =true的时候表示如果某子物体在SetActive(false)及隐藏的时候,我们任然能够得到子物体的T类型组件并且可以操作该组件。 bool =false的时候表示如果某子物体在SetActive(false)及隐藏的时候,我们就不能够得到并且操作子物体的T类型组件,这也是unity的默认值,我们日常使用时在子物体隐藏时,我们也是不能操作子物体下面的某个组件的。
好了就到这里吧~

上一篇 下一篇

猜你喜欢

热点阅读