目录
前文
[Unity] 使用GraphView实现一个可视化节点的事件行为树系统(序章/Github下载)_Sugarzo的博客-CSDN博客_unity graphview
[Unity] GraphView 可视化节点的事件行为树(一) Runtime Node_Sugarzo的博客-CSDN博客
在上一节中,我们已经介绍了Runtime中的节点运行逻辑,这一章节中将进入Editor部分。我们使用的是UI Toolkit的制作我们需要的事件行为树的UI面板。
UI Toolkit 介绍
UI Toolkit是unity推出的一套全新UI系统。对比传统的GUI系统有着一套全新的工作流。在Unity 2021版本后已被内嵌到默认的编辑器中了。使用UI Toolkit可以很方便的构建属于自己的UI工具。在本章节中使用的是Editor UI的制作。
在资源窗口右键,在Create->UI Toolkit->Editor Window中先创建我们需要的Asset。
可以看到一个在UI Toolkit中的UI主要有三个模块组成:UXML,USS,C#。这里的组织结构和Web前端三件套很类似(HTML,CSS,JavaScript)。其中,UXML负责UI的布局和结构,USS负责UI样式,C#脚本负责UI的功能和行为。
双击创建好的UXML,就可以进入UI Builder界面了。这是一个可视化编辑的窗口。中间的窗口就是当前这个UI的预览了。左边的Hierarchy窗口会展示当前UI的所有元素(当前只有一个Label),里面的所有元素都是以树状的父子结构组织起来的。最上面的第一个元素被称为根节点(root)。再点击里面的元素后,右边的Inspector窗口就会显示出该元素的所有属性。左下角的库窗口则是可以使用的UI 元素。
在UI Toolkit的所有UI元素中,Visual Element就是最最基础的元素了,他是所有UI元素的基类。也就是说只有继承Visual Element类才可以成为一个放在UI 布局中的元素。这个元素放在了Library中的第一个。
当然,在UI Toolkit中,放置UI元素也不仅仅局限在UI Builder里放置,也可以在C#脚本里使用代码进行添加。点开刚刚创建好的C#脚本,可以看到里面已经写好了一部分的样例代码,展示了3中在UI窗口中添加元素Label的方法(这里是对Root节点Add)
好了,这里就是UI Toolkit的基本概念了。其中每个元素的具体样例在unity顶部菜单的window-UI Toolkit-Samples中都能找到代码例子,可以自行参考。
制作事件行为树的UI界面
本项目中的事件行为树UI布局参考:
可以看到构造还是比较简单的。左边是节点的Inspector面板,右边就是我们存放节点的网格图。可以从Librar已有元素直接拖入。
关于对齐结构这里介绍几个右边常用的属性:Flex可以调整该元素的比例缩放(数值为0-1)和元素拓展方向(这里看图标用到的是从左到右),Align则是对齐方向。Size可以设置元素的大小(一般我自己会用百分比或者Auto)
实际运行起来的截图如下
在Hirearachy除了本来Library中就有的元素外(在旁边的三点选项中打开Editor extension authoring可以打开Editor模式下的额外拓展包),还有我们自己创建的的两个UI元素:FlowChartView和InspectorView。
前文提到过,想在UI Toolkit中放入我们新的元素,该元素一定继承自VisualElement。实际上我们需要使用的GraphView本身也是一个VisualElement
我们需要的节点区域和Inspector窗口面板的UI元素,就需要我们自己创建了。我们新建脚本,创建这两个元素的C#脚本,让他们继承自VisualElement和GraphView
public class InspectorView : VisualElement
{
public new class UxmlFactory : UxmlFactory<InspectorView, UxmlTraits> { }
}
public class FlowChartView : GraphView
{
public new class UxmlFactory : UxmlFactory<FlowChartView, GraphView.UxmlTraits> { }
}
其中的new class UxmlFactory,可以让该元素显示在UI Builder中,我们就可以在Library-Project中看到我们新建的这两个UI元素,就可以拖入我们的UI窗口编辑了。
默认的GraphView是一片黑屏。在这里,我们给我们的GraphView窗口添加上网格和拖拽缩放功能。
public class FlowChartView : GraphView
{
public new class UxmlFactory : UxmlFactory<FlowChartView, GraphView.UxmlTraits> { }
public FlowChartEditorWindow window;
public FlowChartView()
{
Insert(0, new GridBackground());
this.AddManipulator(new ContentZoomer());
this.AddManipulator(new ContentDragger());
this.AddManipulator(new SelectionDragger());
this.AddManipulator(new RectangleSelector());
var styleSheet = AssetDatabase.LoadAssetAtPath<StyleSheet>("Assets/SugarzoNode/Editor/UIBuilder/FlowChart.uss");
styleSheets.Add(styleSheet);
}
uss代码参考,上面代码的uss路径要根据项目实际路径进行设置。
GridBackground {
--grid-background-color: rgb(40,40,40);
--line-color: rgba(192,196,192,0.1);
--thick-line-color: rgba(193,196,192,0.1);
--spacing: 15;
}
这样,我们的行为树UI就制作好了。
GameObject关联编辑器窗口
最后我们来学习如何打开我们制作好的UI。实际上,创建这个窗口的脚本模板里已经写入了MenuItem,可以在顶部菜单中直接打开这个UI窗口。
但是我们的行为树是挂载到GameObject上的。每个GameObject上都有不同的节点图,自然也对应着不同的窗口数据。我们需要在对应GO的Inspector中打开它。
先新建一个Runtime的FlowChart脚本,这个脚本搭载了MonoBehaviour,并给他添加一个静态方法让可以在物品创建菜单中方便我们直接创建出来。
public class FlowChart:MonoBehaviour
{
#if UNITY_EDITOR
[TextArea]
public string note;
[UnityEditor.MenuItem("GameObject/FlowChart", false, priority = 0)]
private static void CreateFlowChartInScene()
{
var gameObject = new GameObject(typeof(FlowChart).Name);
UnityEditor.Undo.RegisterCreatedObjectUndo(gameObject, "Create");
gameObject.AddComponent<FlowChart>();
if (Selection.activeGameObject != null)
{
gameObject.transform.parent = Selection.activeGameObject.transform;
}
Selection.activeGameObject = gameObject;
}
#endif
}
再写一个Editor的FlowChart脚本,让它在Editor的Inspector中绘制一个按钮,用来打开这个物
品的UI面板(这里使用了一个static存储了数据)。注意本脚本要放在Editor文件夹下。
//在编辑器里绘制FlowChart的Inspector
[CustomEditor(typeof(FlowChart))]
public class FlowChartEditor : Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
//隐藏不需要显示的组件
if (GUILayout.Button("Open"))
{
FlowChartEditorWindow.userSeletionGo = (target as MonoBehaviour)?.gameObject;
FlowChartEditorWindow.OpenWindow();
}
}
}
public class FlowChartEditorWindow : EditorWindow
{
public static void OpenWindow()
{
FlowChartEditorWindow wnd = GetWindow<FlowChartEditorWindow>();
wnd.titleContent = new GUIContent("FlowChart");
}
/// <summary>
/// 当前选择的游戏物品
/// </summary>
public static GameObject userSeletionGo;
}
这样,我们就成功在Inspector中绘制出了一个可以打开我们的行为树UI窗口的按钮了。
本节在这里就结束了。下一章应该就是最后一篇了,会介绍GraphView框架中的具体应用。