目录
创建基础节点
了解节点基本结构
- 主容器(mainContainer)
- 标题容器(titleContainer)
- 标题按钮容器(titleButtonContainer)
- 顶部容器(topContainer)
- 输入容器(inputContainer)
- 输出容器(outputContainer)
- 扩展容器(extensionContainer)
- 标题容器(titleContainer)

创建基础节点类
- 创建文件夹:Assets/E Tool/E Story/Editor/Scripts/UI Node
- 打卡UI Node文件夹,创建C#文件,命名为
BaseNode
- 打开BaseNode.cs,将内容修改如下:
C#
using UnityEditor.Experimental.GraphView;
using UnityEngine;
namespace E.Story
{
// 基类节点
public class BaseNode : Node
{
// UI元素
protected StoryGraphView graphView;
// 初始化
public void Init(StoryGraphView graphView, string title, Vector2 position)
{
this.graphView = graphView;
this.title = title;
SetPosition(new Rect(position, Vector2.zero));
}
// 绘制视图
public virtual void Draw()
{
DrawMainContainer();
DrawTitleContainer();
DrawTitleButtonContainer();
DrawTopContainer();
DrawInputContainer();
DrawOutputContainer();
DrawExtensionContainer();
}
// 绘制主容器
protected virtual void DrawMainContainer()
{
}
// 绘制标题容器
protected virtual void DrawTitleContainer()
{
}
// 绘制标题按钮容器
protected virtual void DrawTitleButtonContainer()
{
}
// 绘制顶部容器
protected virtual void DrawTopContainer()
{
}
// 绘制输入容器
protected virtual void DrawInputContainer()
{
}
// 绘制输出容器
protected virtual void DrawOutputContainer()
{
}
// 绘制扩展容器
protected virtual void DrawExtensionContainer()
{
}
}
}
向视图添加节点
自动添加默认节点
- 打开StoryGraphView.cs,新增
CreateNode
和AddDefaultNodes
方法
C#
// 添加默认节点
private void AddDefaultNodes()
{
AddElement(CreateNode("节点", new Vector2(200, 200)));
}
// 创建节点
public BaseNode CreateNode(string title, Vector2 position)
{
// 创建对应节点
BaseNode node = new();
node.Init(this, title, position);
node.Draw();
return node;
}
- 调用
AddDefaultNodes
方法
C#
public StoryGraphView(StoryEditorWindow window)
{
/* ... 此处代码已省略 ... */
// 调用
AddDefaultNodes();
}
手动添加节点
- 打开StoryGraphView.cs,重写
BuildContextualMenu
方法
C#
// 构建上下文菜单
public override void BuildContextualMenu(ContextualMenuPopulateEvent evt)
{
base.BuildContextualMenu(evt);
// 点击按钮实现添加新节点
evt.menu.AppendAction("添加节点", action =>
{
AddElement(CreateNode("节点", Vector2.zero));
});
}
- 在视图空白处点击鼠标右键即可看见
添加节点
按钮
测试效果
打开插件窗口,当前效果如下:

自定义基础节点
创建节点类型枚举
- 依次创建以下文件夹:
- Assets/E Tool/E Story/Runtime
- Assets/E Tool/E Story/Runtime/Scripts
- Assets/E Tool/E Story/Runtime/Scripts/Data
- 打开Data文件夹,创建C#文件,命名为
NodeType
- 打开NodeType.cs,将内容修改如下:
C#
namespace E.Story
{
// 节点类型
public enum NodeType
{
// 基础
Base = 0,
// 零进零出
ZeroInZeroOut = 1,
// 零进单出
ZeroInSingleOut = 2,
// 零进多出
ZeroInMultiOut = 3,
// 单进零出
SingleInZeroOut = 4,
// 单进单出
SingleInSingleOut = 5,
// 单进多出
SingleInMultiOut = 6,
// 多进零出
MultiInZeroOut = 7,
// 多进单出
MultiInSingleOut = 8,
// 多进多出
MultiInMultiOut = 9,
}
}
新增实用方法
打开ElementUtility.cs,新增CreatePort
方法
C#
// 创建端口
public static Port CreatePort(this BaseNode node, string portName = "", Orientation orientation = Orientation.Horizontal, Direction direction = Direction.Output, Port.Capacity capacity = Port.Capacity.Single)
{
Port port = node.InstantiatePort(orientation, direction, capacity, typeof(bool));
port.portName = portName;
return port;
}
修改基础节点类
- 打开BaseNode.cs,新增以下字段和属性:
C#
// UI元素
protected VisualElement customDataContainer;
protected Foldout foldout;
protected Port input;
protected Port output;
// 节点GUID
public string GUID { get; set; }
// 节点类型
public NodeType Type { get; set; }
// 节点标题
public string Title { get; set; }
// 节点备注
public string Note { get; set; }
- 修改以下方法:
C#
public virtual void Init(StoryGraphView graphView, string title, Vector2 position)
{
// 设置字段
this.graphView = graphView;
SetPosition(new Rect(position, Vector2.zero));
// 设置属性默认值
Type = NodeType.Base;
GUID = UnityEditor.GUID.Generate().ToString();
Title = title;
Note = "备注信息";
}
public virtual void DrawTitleContainer()
{
// 创建标题输入框
TextField tfdTitle = ElementUtility.CreateTextField(Title, null, callback =>
{
// 更新标题
Title = callback.newValue;
});
// 将标题输入框放在最左侧
titleContainer.Insert(0, tfdTitle);
}
public override void DrawInputContainer()
{
// 创建输入端口
input = this.CreatePort("上个节点", Orientation.Horizontal, Direction.Input, Port.Capacity.Multi);
inputContainer.Add(input);
}
public virtual void DrawOutputContainer()
{
// 创建输出端口
output = this.CreatePort("下个节点");
outputContainer.Add(output);
}
public virtual void DrawExtensionContainer()
{
// 创建自定义容器
customDataContainer = new();
// 创建折叠组
foldout = ElementUtility.CreateFoldout("节点内容");
// 创建备注输入框
TextField tfdNote = ElementUtility.CreateTextArea(Note, null, callback =>
{
Note = callback.newValue;
});
// 将目标放到对应容器
foldout.Add(tfdNote);
customDataContainer.Add(foldout);
extensionContainer.Add(customDataContainer);
// 此方法必须调用
RefreshExpandedState();
}
测试效果
打开插件窗口,最终效果如下:
