UNITY编辑器扩展(一)

UNITY编辑器扩展

创建

1,先创建Editor文件夹,代码放在Editor文件夹内。

using UnityEngine;
using UnityEditor;
using System.Collections;
public class EditorTest
{
    [MenuItem("MyTools/EditorTest")]
    public static void ConfigDialog()
    {
        Debug.Log("EditorTest ToolButton is pressed!");
    }
}

2,在代码里,写在这个中间。

#if UNITY_EDITOR
[UnityEditor.MenuItem("Demo")]
#endif

创建组件菜单

using UnityEngine;
using System.Collections;
using UnityEditor;
[AddComponentMenu("菜单组件/MenuTest")]
public class Test1 : MonoBehaviour {
}

上下文菜单(ContextMenu)

using UnityEngine;
using System.Collections;
using UnityEditor;
[AddComponentMenu("菜单组件/MenuTest")]
public class Test1 : MonoBehaviour {
}

附给物体后点右键

关联组件

[RequireComponent(typeof(Rigidbody))]
[AddComponentMenu("菜单组件/MenuTest")]
public class Test1 : MonoBehaviour {
    void Start () {
    
    }
    
    // Update is called once per frame
    void Update () {
    
    }
 
    [ContextMenu("ContextMenu")]
    public void Test()
    {
        Debug.Log("上下文测试");
    }
 
}

此时在一个物体上添加Test.cs组件的同时将Rigidbody组件也添加上去了。在移除这个组件的时候要先移除Test1组件,然后才能移除Rigidbody,否则不能移除成功

扩展Inspector面板

1)隐藏属性显示 (HideInInspector)
2)不显示的属性(NonSerialized)
3)关键字序列化(Serializable)
4)序列化域(SerializeField)


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

[HelpURL("http://www.baidu.com")]
[AddComponentMenu("People")]
public class People : MonoBehaviour
{
    [Header("BaseInfo")]
    [Multiline(5)]
    public string name;
    [Range(1,100)]
    [Space(100)]//设置行间距
    public int age;
[ContextMenu("OutputInfo")]
void OutputInfo()
{
    print(name+"]"+age);
}

}

[ContextMenu(“OutputInfo”)]
可以非运行状态下执行函数

public class Actor : MonoBehaviour {

#region public member
public Vector3 lookAtPoint = Vector3.zero;
public int mAge;
public string mName;
public bool mIsMale;
public string mPath;
public AnimationCurve mCurve;
public Color mColor;
#endregion

}

在这里插入图片描述
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEditor;

[CustomEditor(typeof(Actor))] //编辑对应的脚本
public class ActorEditor : Editor
{

//private string mPath1 = "";
private Actor mActor;

public override void OnInspectorGUI()
{
    Actor t = (Actor)target;
    mActor = t;

    t.mName = EditorGUILayout.TextField("name", t.mName);
    t.mAge = EditorGUILayout.IntField("age", t.mAge);
    t.mIsMale = ETCGuiTools.Toggle("male", t.mIsMale);
    t.transform.position = EditorGUILayout.Vector3Field("position", t.transform.position);

    EditorGUILayout.Space();
    EditorGUILayout.BeginHorizontal(); //被Horizontal包的会显示在同一行
    GUILayout.Label("资源路径:");
    t.mPath = EditorGUILayout.TextField(t.mPath);
    if (GUILayout.Button("浏览"))
        EditorApplication.delayCall += Save; //点击按钮调用的方法
    EditorGUILayout.EndHorizontal();

    EditorGUILayout.Space();
    EditorGUILayout.BeginHorizontal();
    t.mCurve = EditorGUILayout.CurveField("Curves:", t.mCurve);
    EditorGUILayout.EndHorizontal();

    EditorGUILayout.Space();
    EditorGUILayout.BeginHorizontal();
    EditorGUILayout.LabelField("Color:");
    t.mColor = EditorGUILayout.ColorField(t.mColor);
    EditorGUILayout.EndHorizontal();
}

/// <summary>
/// 选择资源存储路径
/// </summary>
void Save()
{
    string path = EditorUtility.OpenFolderPanel("选择要存储的路径", "", "");
    if (path.Length != 0)
    {
        //mPath1 = path;
        mActor.mPath = path; //貌似这里只能通过成员实现,不能传参数。可能是异步的原因
        EditorUtility.FocusProjectWindow();
    }
}

在这里插入图片描述

自定义面板

同样也是create个脚本 TestDrag 丢在 Editor 文件夹下。TestDrag 继承 EditorWindow ,写个静态方法 Init 上面用属性标注 [MenuItem(“MyWindow/TestDrag”)],意思就是会在菜单栏 MyWindow/TestDrag中点击触发弹出TestDrag 的编辑 window,然后重写 OnGUI() 方法具体定制显示需要编辑的东东

using UnityEngine;
using System.Collections;
using UnityEditor;

public class TestDrag : EditorWindow
{
string path;
Rect rect;
bool groupEnabled = true;
string myString = “Hello World”;
bool myBool = true;
float myFloat = 1.23f;

[MenuItem("MyWindow/TestDrag")] //触发弹出TestDrag window的按钮
static void Init()
{
    EditorWindow.GetWindow(typeof(TestDrag));
}

void OnGUI() //绘制window
{
    EditorGUILayout.LabelField("路径", EditorStyles.boldLabel);
    //获得一个长300的框
    rect = EditorGUILayout.GetControlRect(GUILayout.Width(300));
    //将上面的框作为文本输入框
    path = EditorGUI.TextField(rect, path);

    //如果鼠标正在拖拽中或拖拽结束时,并且鼠标所在位置在文本输入框内
    if ((Event.current.type == EventType.DragUpdated
    || Event.current.type == EventType.DragExited)
    && rect.Contains(Event.current.mousePosition))
    {
        //改变鼠标的外表
        DragAndDrop.visualMode = DragAndDropVisualMode.Generic;
        if (DragAndDrop.paths != null && DragAndDrop.paths.Length > 0)
        {
            path = DragAndDrop.paths[0];
        }
    }

    //---------
    GUILayout.Label("Base Settings", EditorStyles.boldLabel);
    myString = EditorGUILayout.TextField("Text Field", myString);

    groupEnabled = EditorGUILayout.BeginToggleGroup("Optional Settings", groupEnabled);
    myBool = EditorGUILayout.Toggle("Toggle", myBool);
    myFloat = EditorGUILayout.Slider("Slider", myFloat, -3, 3);
    EditorGUILayout.EndToggleGroup();
}

}
在这里插入图片描述

sence

同样也是create个脚本 SceneRealTimeFocusEditor 丢在 Editor 文件夹下。
在场景中显示一些按钮、文字什么的
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
using UnityEditor;

///
/// Scene中的按钮扩展:
///
[CustomEditor(typeof(MonoBehaviour), true)]
public class SceneRealTimeFocusEditor : Editor
{
public void OnEnable()
{
active = false;
}
public void OnDisable()
{
active = false;
}

private bool active = false;
void OnSceneGUI()
{
    GameObject[] gos = Selection.gameObjects;
    if (gos != null)
    //if (Selection.activeTransform != null)
    {

        Handles.BeginGUI();
        GUILayout.BeginArea(new Rect(0, 0, 200, 200));
        if (!active)
        {
            if (GUILayout.Button("Active Real Time Trace", GUILayout.Height(30)))
            {
                active = true;
            }
        }
        else
        {
            if (GUILayout.Button("Close Real Time Trace", GUILayout.Height(30)))
            {
                active = false;
            }
        }
        GUILayout.EndArea();
        Handles.EndGUI();

        if (active)
        {
            SceneView.lastActiveSceneView.pivot = gos[0].transform.position;
            //SceneView.lastActiveSceneView.pivot = Selection.activeTransform.position;
            SceneView.lastActiveSceneView.Repaint();
        }
    }
}

}
在这里插入图片描述

using UnityEngine;
using UnityEditor;
using System.Collections;
using System.Text;

///
/// 实时显示场景中的对象
///
public class SceneEditorWindow : EditorWindow
{

RaycastHit _hitInfo;
SceneView.OnSceneFunc _delegate;
static SceneEditorWindow _windowInstance;

private GameObject[] mSelectObjs = null;

[MenuItem("MyWindow/Scene Editor #`")] //快捷方式:shift+`
static void Init()
{
    if (_windowInstance == null)
    {
        _windowInstance = EditorWindow.GetWindow(typeof(SceneEditorWindow)) as SceneEditorWindow;
        _windowInstance._delegate = new SceneView.OnSceneFunc(OnSceneFunc);
        SceneView.onSceneGUIDelegate += _windowInstance._delegate;

    }
}

void OnEnable()
{
}

void OnDisable()
{
}

void OnDestroy()
{
    if (_delegate != null)
    {
        SceneView.onSceneGUIDelegate -= _delegate;
    }
}

void OnSelectionChange()
{
    mSelectObjs = Selection.gameObjects;
}

void OnGUI()
{
    EditorGUILayout.LabelField("All Selected Objects", EditorStyles.boldLabel);

    if (mSelectObjs != null)
    {
        for (int i = 0; i < mSelectObjs.Length; ++i)
        {
            EditorGUILayout.BeginHorizontal();
            GameObject go = mSelectObjs[i];
            EditorGUILayout.Vector3Field(go.name, go.transform.position);
            EditorGUILayout.EndHorizontal();
        }
    }
}

void OnInspectorGUI()
{
    Debug.Log("OnInspectorGUI");
}

static public void OnSceneFunc(SceneView sceneView)
{
    _windowInstance.CustomSceneGUI(sceneView);
}

void CustomSceneGUI(SceneView sceneView)
{
    Camera cameara = sceneView.camera;
    Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
    if (Physics.Raycast(ray, out _hitInfo, 10000, -1))
    {
        //Debug.DrawRay(ray.origin, ray.direction, Color.yellow);
        Vector3 origin = _hitInfo.point;
        origin.y += 100;
        if (Physics.Raycast(origin, Vector3.down, out _hitInfo))
        {
            Handles.color = Color.yellow;
            Handles.DrawLine(_hitInfo.point, origin);
            float arrowSize = 1;
            Vector3 pos = _hitInfo.point;
            Quaternion quat;
            Handles.color = Color.green;
            quat = Quaternion.LookRotation(Vector3.up, Vector3.up);
            Handles.ArrowCap(0, pos, quat, arrowSize);
            Handles.color = Color.red;
            quat = Quaternion.LookRotation(Vector3.right, Vector3.up);
            Handles.ArrowCap(0, pos, quat, arrowSize);
            Handles.color = Color.blue;
            quat = Quaternion.LookRotation(Vector3.forward, Vector3.up);
            Handles.ArrowCap(0, pos, quat, arrowSize);
            //Handles.DrawLine(pos + new Vector3(0, 3, 0), pos);
        }
    }
    SceneView.RepaintAll();
}

}
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值