结果
只实现了选中的对象中包含不超过一个的目标对象时显示图标
实现了选中任意个对象并在对应位置显示辨识图标,并且选中父对象时,满足条件的子对象也会显示
起因
我正在编写一个打怪游戏,我通过在地图上放置预制体“刷怪点”来控制对象的生成,使用脚本变量控制刷怪点生成的怪物属性,但是这些刷怪点在场景是没有贴图的,选中后只有线框,我不能整体的预览到怪物分布情况,所以我希望在我选中这些刷怪点时,场景会绘制图标来展示信息
过程
第一版
使用继承了Editor类的编辑器脚本来实现,只能在选中对象中满足条件的对象为单个时显示图标
[CustomEditor(typeof(SMP))]
public class SMPObjectEditor : Editor
{
public Texture2D icon;
private void OnSceneGUI()
{
// 判断当前是否选中一个SMP脚本挂载的对象
SMP smp = target as SMP;
if (smp != null && Selection.activeGameObject == smp.gameObject)
{
Handles.BeginGUI();
GUI.DrawTexture(new Rect(HandleUtility.WorldToGUIPoint(smp.transform.position), new Vector2(32, 32)), icon);
Handles.EndGUI();
}
}
}
第二版
可以选择多个满足条件的对象并在对应位置显示图标
使用[InitializeOnLoad]属性在Unity加载时自动初始化脚本
[InitializeOnLoad]
public class SMPObjectEditor
{
public static Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/2DBeginnerTutorialResources/Art/Sprites/Characters/EnemyIcon.png");
static SMPObjectEditor()
{
// 注册一个回调函数,在每帧场景视图中绘制SMP对象的Icon
SceneView.duringSceneGui += OnSceneViewGUI;
}
private static void OnSceneViewGUI(SceneView sceneView)
{
// 遍历所有被选中的对象
foreach (GameObject obj in Selection.gameObjects)
{
// 如果对象上挂载了SMP组件,就在场景中绘制Icon
if (obj.GetComponent<SMP>() != null)
{
Handles.BeginGUI();
GUI.DrawTexture(new Rect(HandleUtility.WorldToGUIPoint(obj.transform.position) - new Vector2(32, 32), new Vector2(64, 64)), texture);
Handles.EndGUI();
}
}
}
}
最终版
将满足条件的对象都保存在列表里,然后遍历列表绘制图标,要注意BeginGUI和EndGUI要每次遍历都执行,写在外面就只会绘制最后一个
[InitializeOnLoad]
public class SMPObjectEditor
{
public static Texture2D texture = AssetDatabase.LoadAssetAtPath<Texture2D>("Assets/2DBeginnerTutorialResources/Art/Sprites/Characters/EnemyIcon.png");
static SMPObjectEditor()
{
// 注册一个回调函数,在每帧场景视图中绘制SMP对象的Icon
SceneView.duringSceneGui += OnSceneViewGUI;
}
private static void OnSceneViewGUI(SceneView sceneView)
{
// 遍历所有被选中的对象
foreach (GameObject obj in Selection.gameObjects)
{
// 找出选中对象中挂载了SMP脚本的对象
SMP[] sMPs = obj.GetComponentsInChildren<SMP>();
if (sMPs != null)
{
foreach (SMP smp in sMPs)
{
Handles.BeginGUI();
GUI.DrawTexture(new Rect(HandleUtility.WorldToGUIPoint(smp.transform.position) - new Vector2(32, 32), new Vector2(64, 64)), texture);
Handles.EndGUI();
}
}
}
}