简体   繁体   English

在Unity / C#中动态创建CustomEditor类

[英]Dynamically creating a CustomEditor class in Unity / C#

I am trying to implement edit-mode scripts in my Unity project. 我正在尝试在Unity项目中实现编辑模式脚本。 The idea is that a script can be attached to an object and as it's edited, attributes like scale/position/rotation can be seen updating. 这个想法是脚本可以附加到对象上,并且在对其进行编辑时,可以看到缩放/位置/旋转等属性正在更新。

Without writing an edit mode script, all this stuff is possible, but the changes are not visible until the play button is pressed. 如果不编写编辑模式脚本,则所有这些工作都是可能的,但是直到按下播放按钮,更改才可见。 That's the difference here. 这就是这里的区别。

I'm using a variation of the script provided here to do this. 我正在使用此处提供的脚本的变体来执行此操作。

First of all I have a MonoBehavior script attached to my game object - it looks like so: 首先,我在游戏对象上附加了MonoBehavior脚本-看起来像这样:

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

[ExecuteInEditMode]
public class FlippersEditMode : MonoBehaviour {
    public float extraScale = 1f;
    public void updateEditorState() {
        transform.localScale = (Vector3.up * extraScale);
    }
}

Second I have a script in the Editor folder that calls this updateEditorState method whenever a "Update" button is pressed: 其次,我在Editor文件夹中有一个脚本,每当按下“更新”按钮时,该updateEditorState就会调用此updateEditorState方法:

using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(FlippersEditMode))]
public class FlipperEditModeMeta: Editor {
    public override void OnInspectorGUI() {
        base.OnInspectorGUI();
        if (GUILayout.Button("Update")) {
            if (target.GetType() == typeof(FlippersEditMode)) {
                FlippersEditMode flippers = (FlippersEditMode)target;
                flippers.updateEditorState();
            }
        }
    }
}

This works fine and I'm thankful for that, but this last chunk of code is pure boilerplate. 一切正常,对此我很感激,但是最后这段代码纯属简单。 I will need to have a nearly-identical one of these files for each script that I want to effect edit mode. 我要影响编辑模式的每个脚本都需要有一个几乎相同的文件。

So I started on trying to make a "meta" editor script. 因此,我开始尝试制作“元”编辑器脚本。 The idea is that this script would have an array of slots that the developer can drag scripts into. 想法是,此脚本将具有开发人员可以将脚本拖入其中的一系列插槽。 Each script dragged here will get a CustomEditor class defined like the one shown above. 拖到此处的每个脚本都将获得一个CustomEditor类,该类的定义如上所示。 Of course the classes being dragged here would each need to implement updateEditorState but that's the only requirement of the protocol. 当然,被拖到此处的类每个都需要实现updateEditorState但这是该协议的唯一要求。

So if I make another editor script that looks like this: 因此,如果我制作另一个如下所示的编辑器脚本:

using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(EditModeScripts))]
public class EditModeScriptsMeta : Editor {
    public override void OnInspectorGUI() {
        base.OnInspectorGUI();
        if (GUILayout.Button("Update")) {
            if (target.GetType() == typeof(EditModeScripts)) {
                EditModeScripts edit_mode_scripts = (EditModeScripts)target;
                edit_mode_scripts.updateEditorState()
            }
        }
    }
}

Then I can trigger the updateEditorState function in the following: 然后,我可以在下面触发updateEditorState函数:

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

public class EditModeScripts : MonoBehaviour {

    public MonoBehaviour[] scripts = {};

    public void updateEditorState () {
        for (int i = 0; i < scripts.Length; i++) {
            MonoBehaviour script = scripts[i];
            // How to generate an editor class here for each script?
        }
    }
}

But as you can see I don't know how to dynamically generate the classes. 但是如您所见,我不知道如何动态生成类。

I don't think your approach will work purely dynamically. 我认为您的方法不会完全动态地起作用。 Unity compiles your code everytime you change something and come back to unity. 每当您更改某些内容并回到统一状态时,Unity都会编译您的代码。 After compiling it Unity uses Reflection to determine which editors are available. 编译后,Unity使用Reflection确定可用的编辑器。

You could theoretically create new source files which contain the editor code. 从理论上讲,您可以创建包含编辑器代码的新源文件。 I don't know though whether it will automagically reimport the scripts or you need to manually trigger the reimport. 我不知道它是否会自动重新导入脚本,还是您需要手动触发重新导入。

For manually reimporting you can use a combination of AssetDatabase.Refresh() and if that is not enough, select the script asset via the Selection class and trigger the reimport menu entry using EditorApplication.ExecuteMenuItem . 对于手动重新导入,可以使用AssetDatabase.Refresh()的组合,如果还不够,请通过Selection类选择脚本资产,然后使用EditorApplication.ExecuteMenuItem触发重新导入菜单项。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM