编辑器扩展(控制某场景同一类型(所有挂载同一脚本)的物体)
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的默认值,我们日常使用时在子物体隐藏时,我们也是不能操作子物体下面的某个组件的。
好了就到这里吧~