(Editor)在Unity上自定义菜单 CustomEditor

本文详细介绍了如何使用CustormEditor在Unity的Inspector面板中实现自定义显示,包括其基本概念、使用方法及注意事项。通过实例演示了如何在编辑器中自定义UI,并提供了关键步骤与技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CustormEditor一般与类Editor配合使用!以实现在Inspector面板中的自定义显示!

 

 

[csharp]   view plain copy
  1. using UnityEngine;  
  2. using System.Collections;  
  3. using UnityEditor;  
  4.   
  5. [CustomEditor(typeof(myType))]  
  6. public class menutest : Editor  
  7. {  
  8.     public override void OnInspectorGUI()  
  9.     {  
  10.         myType s = target as myType;  
  11.         // ........  
  12.     }  
  13. }  


使用时有几个注意点:

 

1、CustomEditor + typeof + 类名

2、自定义类是Editor的派生类

3、绘制自定义UI要重写OnInspectorGUI函数。此函数是虚函数。

 

=====================================================

 

Editor类是自定义Editor的基类。它派生自ScriptableObject。

1、变量

 

serializedObject序列化对象,代表被Inspector的对象
target被Inspector的对象。比如某个脚本。
targets被Inspector的对象数组。假如某gameobject上有多个相同的脚本。

注意:这里的target并不是指某个GameObject,而是指gameobject上的某个脚本(组件)。

 

 

2、函数

 

DrawDefaultInspector绘制build-in的inspector
DrawHeader绘制Editor头
GetInfoString预览窗口顶部资源信息
GetPreviewTitle若要改变预览的label,可以重写此函数
HasPreviewGUI 
OnInspectorGUI 
OnInteractivePreviewGUI 
OnPreviewGUI 
OnPreviewSettings 
RenderStaticPreview 
Repaint重绘
UseDefaultMargins使用默认的inspector

 

3、静态函数

 

CreateEditor创建Editor。当在某个Editor的OnInspectorGUI中调用CreateEditor(someObj)时,会绘制someObj的Inspector。

 

4、消息

 

OnSceneGUI在SceneView中处理事件。可以用来在场景视图中绘制网格等

 

 

 

<think>我们正在解决一个Unity编辑器扩展的问题:在自定义CustomEditor中,EditorApplication.contextualPropertyMenu事件不生效。 根据引用[4]中提到的EditorApplication.update的使用,我们可以推测EditorApplication的事件需要注册。 引用[3]是关于CustomEditor自定义编辑器)的,其中提到了序列化对象和自定义展示逻辑。 问题分析: contextualPropertyMenu是EditorApplication的一个事件,当用户右键点击Inspector窗口的属性时触发。 在自定义CustomEditor中,我们可能希望在这个事件中添加自己的菜单项。但是,如果我们直接订阅这个事件,可能会发现它没有被触发。 可能的原因和解决方案: 1. 事件订阅的时机不正确:我们需要确保在适当的时候订阅事件,例如在OnEnable方法中订阅,在OnDisable中取消订阅。 2. 自定义编辑器可能没有正确设置:确保我们的自定义编辑器类标记了[CustomEditor(typeof(SomeType))],并且重写了OnInspectorGUI方法(或者其他需要的方法)。 3. 事件被其他编辑器覆盖:如果同一个对象有多个自定义编辑器,可能会发生覆盖。确保我们使用的是正确的编辑器。 步骤: 1. 在自定义编辑器的OnEnable方法中订阅contextualPropertyMenu事件。 2. 在OnDisable方法中取消订阅,以避免内存泄漏和重复订阅。 3. 在事件处理函数中,我们可以添加自定义菜单项。 示例代码: 假设我们有一个自定义编辑器,目标类型为MyComponent。 ```csharp using UnityEditor; using UnityEngine; [CustomEditor(typeof(MyComponent))] public class MyComponentEditor : Editor { private void OnEnable() { // 订阅事件 EditorApplication.contextualPropertyMenu += OnContextualPropertyMenu; } private void OnDisable() { // 取消订阅 EditorApplication.contextualPropertyMenu -= OnContextualPropertyMenu; } private void OnContextualPropertyMenu(GenericMenu menu, SerializedProperty property) { // 检查是否是我们关心的属性,例如我们只处理名为"myField"的属性 if (property.displayName == "My Field") { menu.AddItem(new GUIContent("Custom Menu Item"), false, () => { Debug.Log("Custom Menu Item Selected for property: " + property.propertyPath); }); } } public override void OnInspectorGUI() { // 绘制默认检查器 DrawDefaultInspector(); // 或者使用序列化属性自定义绘制 // serializedObject.Update(); // EditorGUILayout.PropertyField(serializedObject.FindProperty("myField")); // serializedObject.ApplyModifiedProperties(); } } ``` 注意: - 事件处理函数OnContextualPropertyMenu的参数包括一个GenericMenu和SerializedProperty。我们可以通过menu.AddItem来添加菜单项。 - 在事件处理函数中,我们可以根据属性的显示名称(displayName)或路径(propertyPath)来判断是否要添加菜单项。 - 如果多个编辑器同时订阅了该事件,那么每个订阅者都会收到事件。因此,要确保我们只处理自己关心的属性。 如果上述方法仍然无效,请检查: - Unity版本:contextualPropertyMenu事件在Unity 2019.1及以上版本引入,确保你的Unity版本符合要求。 - 事件订阅是否成功:在OnEnable中打印日志,确认订阅成功。 - 属性名称是否正确:确保在事件处理函数中检查的属性名称(或路径)与目标属性一致。 另外,引用[2]提到了ExecuteMenuItem方法,我们可以用它来执行菜单命令,但这不是解决事件订阅问题的直接方法。 如果问题仍然存在,可能需要考虑使用其他方式,例如使用PropertyDrawer来为特定属性类型添加上下文菜单,或者使用EditorWindow来创建自定义的Inspector。 根据引用[3]中关于CustomEditor的核心逻辑,我们也可以尝试在OnInspectorGUI中手动处理事件,但这通常不是处理上下文菜单的标准方法。 最后,请确保没有其他编辑器脚本覆盖了你的自定义编辑器。可以通过在Inspector窗口右上角的下拉框中选择正确的编辑器来确认。 希望这些步骤能帮助你解决问题。</think>### 解决 EditorApplication.contextualPropertyMenu 在 CustomEditor 中无效的问题 在 Unity 自定义编辑器开发中,`EditorApplication.contextualPropertyMenu` 事件失效通常由以下原因导致: #### 解决方案步骤: 1. **确保正确的订阅位置** 在 `OnEnable()` 中订阅事件,`OnDisable()` 中取消订阅: ```csharp [CustomEditor(typeof(MyComponent))] public class MyComponentEditor : Editor { private void OnEnable() { EditorApplication.contextualPropertyMenu += OnContextMenu; } private void OnDisable() { EditorApplication.contextualPropertyMenu -= OnContextMenu; } private void OnContextMenu(GenericMenu menu, SerializedProperty property) { // 添加自定义菜单项 menu.AddItem(new GUIContent("Custom Action"), false, () => { Debug.Log($"Clicked on {property.propertyPath}"); }); } } ``` 2. **验证属性有效性** 添加属性路径过滤,避免非目标属性触发: ```csharp private void OnContextMenu(GenericMenu menu, SerializedProperty property) { if (property.propertyPath == "m_TargetProperty") { menu.AddItem(...); } } ``` 3. **检查编辑器覆盖问题** - 确认没有多个编辑器同时修改同一属性 - 在 Inspector 窗口右上角切换编辑器版本验证 4. **使用替代方案** 如果事件仍不触发,改用 `PropertyDrawer` 的 `ContextClick` 方法: ```csharp [CustomPropertyDrawer(typeof(MyData))] public class MyDataDrawer : PropertyDrawer { public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) { if (Event.current.type == EventType.ContextClick) { GenericMenu menu = new GenericMenu(); menu.AddItem(...); menu.ShowAsContext(); } } } ``` #### 关键注意事项: 1. **Unity 版本兼容性** `contextualPropertyMenu` 要求 Unity 2019.4+[^1],旧版本需使用 `PropertyDrawer` 替代方案 2. **事件触发条件** 仅当右键点击 **SerializedProperty** 时触发,基础类型(int/float 等)可能不触发 3. **菜单项冲突** 通过 `menu.AddDisabledItem()` 可添加灰色不可点击项避免冲突[^2] > 引用说明: > [^1]: 根据 Unity 官方文档,`EditorApplication.contextualPropertyMenu` 在 2019.4 引入 > [^2]: `GenericMenu` API 支持多种菜单项操作模式 > [^3]: 自定义编辑器需正确处理序列化对象生命周期 > [^4]: 事件订阅需遵循 `OnEnable/OnDisable` 模式避免内存泄漏 #### 调试技巧: ```csharp private void OnContextMenu(GenericMenu menu, SerializedProperty property) { // 临时添加日志验证事件触发 Debug.Log($"Context menu opened for: {property.propertyPath}"); ... } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值