Unity Graph View打造图形化对话编辑系统(三)

Unity Graph View打造图形化对话编辑系统(三)——UIBuilder构造Editor Window

目录

  • 一、效果展示及实现思路
  • 二、数据节点抽象
  • 三、UIBuilder构造EditorWindow
  • 四、实现EditorWindow各类视图类
  • 五、实现运行组件,让对话系统跑起来

视频效果演示

Graph View打造图形化对话编辑系统效果展示

最终源码先附在此

点击此处下载源码


先得写几个类

编辑窗口分成左右两部分,左边是属性窗口(Inspector),当用户选择了一个节点时,可以在这里编辑它。右边是对话树的编辑窗口,编辑工作主要在这里进行。那么我们需要以下几个类:

  • HorizontalSplitView —— 水平方向分割窗口视图类,继承自TwoPaneSplitView
  • DialogueTreeView —— 对话树视图类,它是节点和连线的容器,继承自GraphView
  • DialogueNodeView —— 节点视图类,它负责渲染节点,是接口的容器,继承自Node
  • InspectorView —— 节点属性编辑面板,继承自VisualElement

这几个类,因为只需要运行在编辑模式中,所以,最好把他们放到Editor文件夹下面,这样可以确保在发布时不会将他们打包进工程。

以DialogueTreeView为例:

public class DialogGraphView : GraphView
{
    public new class UxmlFactory : UxmlFactory<DialogGraphView, UxmlTraits> { }

	// 对话树的Scriptable数据
    public DialogTree treeData = null;

    public DialogGraphView()
    {
    	// 增加格子背景、内容缩放、拖动、框选组件。
        Insert(0, new GridBackground());
        this.AddManipulator(new ContentZoomer());
        this.AddManipulator(new ContentDragger());
        this.AddManipulator(new SelectionDragger());
        this.AddManipulator(new RectangleSelector());

		// 加载uss风格文件,类似HTML里的css
        var styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/Dialog Graph/Editor/EditorWindow/DialogGraphWindow.uss");
        styleSheets.Add(styleSheet);
    }
}

用UIBuilder搭建如下的UI(注意左侧层级关系):
Unity Graph View打造图形化对话编辑系统(三)_第1张图片
需要注意的一个小坑:
InspectorView和DialogueTreeView,不要直接隶属面板容器,或者说他们不要有兄弟面板,否则就会导致鼠标位置响应不准确。要先给他套上一个VisualElement。这UIBuilder目前还是preview状态,尚未正式发布,所有还有一些各种各样的小问题。
默认情况下,打开我们自己定义的编辑窗口,是通过自定义的菜单来实现的,但是,我们想让我们的编辑窗口关联到Scriptable数据上,我们想让用户双击DialogTree时,能够自动打开编辑窗口,然后对该DialogTree进行编辑,所以,我们需要修改一下窗口的代码:

public class DialogGraphWindow : EditorWindow
{
    /*
    这是之前的打开方式,我们不再需要它了
    [MenuItem("Dialog Graph/Editor Window")]
    public static void OpenEditorWindow()
    {
        DialogGraphWindow wnd = GetWindow();
        wnd.titleContent = new GUIContent("DialogGraphWindow");
    }
    */

	// 当双击Assets时,如果双击的是一颗对话树,那我们就编辑它
    [OnOpenAsset(1)]
    public static bool OnOpenAssets(int id, int line)
    {
        if( EditorUtility.InstanceIDToObject(id) is DialogTree tree )
        {
            DialogGraphWindow wnd = GetWindow<DialogGraphWindow>();
            wnd.titleContent = new GUIContent($"图形化对话系统");
            Label titleLab = wnd.rootVisualElement.Q<Label>("TreeViewTitle");
            if( titleLab != null )
                titleLab.text = $"对话图 - {tree.name}";
            wnd.graphView.Populate(tree);
            return true;
        }
        return false;
    }

    public static void CloseEditorWindow()
    {
        DialogGraphWindow wnd = GetWindow<DialogGraphWindow>();
        wnd.Close();
    }

    private DialogGraphView graphView = null;
    private InspectorView inspectorView = null;

    public void CreateGUI()
    {
        var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Dialog Graph/Editor/EditorWindow/DialogGraphWindow.uxml");
        visualTree.CloneTree(rootVisualElement);

        graphView = rootVisualElement.Q<DialogGraphView>("GraphView");
        graphView.OnNodeSelected += WhenNodeSelected;

        inspectorView = rootVisualElement.Q<InspectorView>("Inspector");

        Button bt = rootVisualElement.Q<Button>("SaveButton");
        bt.clicked += OnSaveButtonClicked;
    }

    private void OnSaveButtonClicked()
    {
        AssetDatabase.SaveAssets();
    }

    private void OnDestroy()
    {
        AssetDatabase.SaveAssets();
    }
}

还有一个问题,如果用户双击了一个DialogTree,进入了编辑状态,然后它又将这个DialogTree删除了,怎么办?此时我们的编辑窗口所编辑的目标已经消失了,窗口应该要自动关闭才合理。所以,我们需要监听这种事情的发生。查阅资料后,果然有一个方法:

public class CloseEditorBeforeAssetRemoved : UnityEditor.AssetModificationProcessor
{
    public static AssetDeleteResult OnWillDeleteAsset(string assetPath, RemoveAssetOptions option)
    {
        if( AssetDatabase.LoadAssetAtPath<DialogTree>(assetPath) is DialogTree tree )
        {
            DialogGraphWindow.CloseEditorWindow();
        }
        return AssetDeleteResult.DidNotDelete;
    }
}

你可能感兴趣的:(Unity,unity,Graph,View,节点编辑器,对话系统,UIBuilder)