xNode简单使用

  • xNode中最基本的4个类
  • NodeGraph
  • Node
  • NodeEditor
  • NodeGraphEditor
  • 总结



最近想用做一个剧情的编辑器,本来想用Untiy自己带的编辑器扩展API进行开发,然后想到了能不能做一个基于节点编辑对话的插件,于是想着先做出节点编辑器,但是发现对于重新开发一个基于节点的插件比较麻烦,然后就看到了xNode这个插件,于是就研究了一下,xNode本身没有任何功能,但是它提供了基本的Graph和Node的创建,使得很方便让我们自定义节点。

xNode中最基本的4个类

  1. Node
  2. NodeEditor
  3. NodeGraph
  4. NodeGraphEditor

有了这几个类基本就可以自定义你想要的节点类型了。他们可以看作分为2组,1和2代表着关于节点的一些设置,3和4代表着图的设置。其中Node、NodeGraph都是继承自ScriptableObject的,所以他们创建出来都是以资源的形式储存在Unity项目中。

NodeGraph

在创建节点之前先要有一个图的窗口,用来存放节点。

我们可以创建一个类DialogueGragh继承NodeGraph这样就可以直接右键Create一个图的窗口出来。

xNode已经给我们设置好了脚本的模板我们也可以通过右键快速创建一个继承NodeGraph的脚本。

unity中UITree子节点选中父节点一起高亮 unity 节点编辑器_连线

[Serializable, CreateAssetMenu(fileName = "New Math Graph", menuName = "xNode Examples/Dialog Graph")]
//我们可以更改创建菜单的属性来修改创建图时候的位置
public class DialogGraph : NodeGraph
{
}

之后我们可以右键看到创建图的选项

unity中UITree子节点选中父节点一起高亮 unity 节点编辑器_unity_02


创建之后的图是空的什么都没有

unity中UITree子节点选中父节点一起高亮 unity 节点编辑器_unity_03


创建好了之后发现他是资源文件方便我们修改。

Node

之后我们就要创建节点了我们也想刚才一样创建一个脚本,这回继承的是Node

public class ChatNode : Node {

	// Use this for initialization
	protected override void Init() {
		base.Init();
		
	}

	// Return the correct value of an output port when requested
	public override object GetValue(NodePort port) {
		return null; // Replace this
	}
}

如果你使用模板创建的他会自动重写两个方法,Init是初始化用的,GetValue是一个根据端点返回一个值类型是object。

创建好了我们就可以返回Unity创建节点了,但是这次我们是打开刚才创建的哪个图的资源,在图中点右键创建节点,选择我们刚才写的脚本名字的节点。

unity中UITree子节点选中父节点一起高亮 unity 节点编辑器_Graph_04


创建了一个空的节点什么都没有。

我们可以在节点的脚本里给他添加字段让他显示我们想要看到的数据。

public int DialogID;
	public string Name;
	[TextArea]
	public string Content;

保存返回Unity可以看到节点的字段信息被现实出来了。

unity中UITree子节点选中父节点一起高亮 unity 节点编辑器_ide_05


这里很像我们的Inspector面板。

之后对于节点的编辑器肯定少不了连线,像Shader Graph、Behaior designer、Animator这些面板都是能够连线的。这里xNode提供了一种NodePort的类,我的理解是他是一个端点类,连线必须从一个端点到另一个端点,它分为两类一种是输入端,一种是输出端,输入端不能连出线。

那我们可以创建一个输入端和输出端看看,端点的创建就是一个字段加上一个属性输入用[Input],

输出用[Output]。我们可以给端点指定类型一边传递数据。

[Input]
	public int enter;
	[Output]
	public int exit;

这样我们返回Unity就可以看到端点显示了而且输出端也可以正常连线了。

unity中UITree子节点选中父节点一起高亮 unity 节点编辑器_Graph_06


我们可以参考xNode给的实例定义各种的节点类型,我也按着他给的github上一个对话实例参考着做出了一个编辑对话的节点编辑器。

unity中UITree子节点选中父节点一起高亮 unity 节点编辑器_Graph_07


你可以定义各种类型的节点使你的编辑器更加丰富,功能更加多彩,这里就不多做介绍了。

NodeEditor

接下来我们介绍另外两个类,这两个类都是对编辑器的一些从新绘制。对于编辑器扩展熟悉的应该对下面都能看得懂了。他其实就是对Unity编辑器扩展API的一些封装增加了一些绘制节点和图的功能。

比如,如果我们想让图片显示在节点上,而不是Unity默认的资源那样显示。

不想这样显示:

unity中UITree子节点选中父节点一起高亮 unity 节点编辑器_unity_08


而是这样:

unity中UITree子节点选中父节点一起高亮 unity 节点编辑器_ide_09


我们就要从新绘制这个面板

我们创建一个类继承NodeEditor

[CustomNodeEditor(typeof(Chat))]//
public class ChatNodeEditor : NodeEditor//这里要继承NodeEditor
{
	//绘制标题
    public override void OnHeaderGUI()
    {
        //基本标题可以修改的
        //base.OnHeaderGUI();
        GUI.color = Color.white;
        Chat node = target as Chat;
        DialogGraph graph = node.graph as DialogGraph;
        if (graph.current == node) GUI.color = Color.blue;
        string title = target.name;
        GUILayout.Label(title, NodeEditorResources.styles.nodeHeader, GUILayout.Height(30));
        GUI.color = Color.white;
    }
	//绘制主体
    public override void OnBodyGUI()
    {
        //base.OnBodyGUI();
        Chat node = target as Chat;
        //开始绘制

        GUILayout.BeginVertical();
        NodeEditorGUILayout.PortField(new GUIContent("enter"), target.GetInputPort("enter"), GUILayout.MinWidth(0));
        NodeEditorGUILayout.PortField(new GUIContent("exit"), target.GetOutputPort("exit"), GUILayout.MinWidth(0));
        GUILayout.EndVertical();

        //绘制贴图fa
        node.DialogID = EditorGUILayout.IntField("DialogID", node.DialogID);
        node.Name = EditorGUILayout.TextField("Name", node.Name);
        node.texture = EditorGUILayout.ObjectField("增加一个贴图", node.texture, typeof(Texture), true) as Texture;
        EditorGUILayout.LabelField("Content:");
        node.content = EditorGUILayout.TextArea(node.content,GUILayout.MinHeight(100));



        //结束绘制
        DialogGraph graph = node.graph as DialogGraph;
        if (GUILayout.Button("MoveNext Node")) node.MoveNext();


        //if (GUILayout.Button("Continue Graph")) graph.Continue();
        if (GUILayout.Button("输出对话"))
        {
            node.ShowDiolog();
            //graph.current = node;
        } 
    }

    public override int GetWidth()
    {
        return 300;
    }
}

NodeGraphEditor

有了上面的介绍那么这个类一样,这个是对图的从新绘制,我们可以绘制几个按钮固定在上面方便我们,从新回到对话原点。

总结

xNode是一个很方便扩展简易的一个节点编辑插件,我们可以使用它做出很棒的编辑器,我也简单录了一个视频以供学习。