前言
unity内置的几个组件又丑又不好看,网上关于ui toolkit的介绍又少之甚少,今天分享两个方法如何自定义ui toolkit组件。
一、方法一
1. 设计
这里通过uxml文件来设置组件的样式,添加uxml文件:
右键鼠标:Create|UI ToolKit|UI Document
添加好后设计一个自定义控件,我这里用一个带标题的版面容器(TitleContainer)举例:
<!--TitleContainer.uxml-->
<ui:UXML
xmlns:ui="UnityEngine.UIElements"
xmlns:uie="UnityEditor.UIElements"
xsi="http://www.w3.org/2001/XMLSchema-instance"
engine="UnityEngine.UIElements"
editor="UnityEditor.UIElements"
noNamespaceSchemaLocation="../../../../UIElementsSchema/UIElements.xsd" editor-extension-mode="False">
<ui:VisualElement
style="flex-grow: 1; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; border-left-color: rgb(64, 64, 64); border-right-color: rgb(64, 64, 64); border-top-color: rgb(64, 64, 64); border-bottom-color: rgb(64, 64, 64); background-color: rgb(42, 42, 42);">
<ui:Label
tabindex="-1"
text="PANEL TITLE"
parse-escape-sequences="true"
display-tooltip-when-elided="true"
style="color: rgb(255, 255, 255); -unity-font-style: bold; padding-left: 10px;" />
<ui:VisualElement
style="flex-grow: 1; padding-top: 10px; padding-right: 10px; padding-bottom: 10px; padding-left: 10px;" />
</ui:VisualElement>
</ui:UXML>
效果是这样滴:
他的对象层级关系:
2. 加载
有了结构之后还需要一个脚本来控制它的行为,这里创建一个脚本叫TitleContainer.cs
using UnityEngine;
using UnityEngine.UIElements;
public class TitleContainer : VisualElement
{
public new class UxmlFactory : UxmlFactory<TitleContainer>
{
}
// 组件的根组件
private VisualElement m_RootElement;
// 标题
private Label m_Title;
// 挂载子组件的组件
private VisualElement m_ContentView;
// 用来设置子组件挂载到哪一个组件
public override VisualElement contentContainer => m_ContentView;
public TitleContainer()
{
// TemplateContainer 用来管理添加的自定义组件结构
TemplateContainer container = new TemplateContainer();
this.hierarchy.Add(container);
// 加载自定义组件结构文件然后放进 TemplateContainer,这边...是你自己的路径
VisualTreeAsset asset = Resources.Load<VisualTreeAsset>(".../TitleContainer");
asset.CloneTree(container);
// 通过 TemplateContainer 获取结构子组件
m_RootElement = container[0];
m_Title = (Label)m_RootElement[0];
m_ContentView = m_RootElement[1];
}
}
然后在UIBuilder的这个地方
就可以看到我们自定义的组件了
可以看到结构文件被添加到TemplateContainer下。
如果你觉得这样子太过于臃肿,可以试试方法二。
二、方法二
1. 设计 + 加载
第二种方法则是通过代码来添加组件:
using UnityEngine.UIElements;
public class TitleContainer : VisualElement
{
public new class UxmlFactory : UxmlFactory<TitleContainer>
{
}
// 组件的根组件
private VisualElement m_RootElement;
// 标题
private Label m_Title;
// 挂载子组件的组件
private VisualElement m_ContentView;
// 用来设置子组件挂载到哪一个组件
public override VisualElement contentContainer => m_ContentView;
public TitleContainer()
{
this.hierarchy.Add(m_RootElement = new VisualElement() { name = "-root" });
m_RootElement.hierarchy.Add(m_Title = new Label() { name = "-title" });
m_RootElement.hierarchy.Add(m_ContentView = new VisualElement() { name = "-content-view" });
// 然后动态加载样式表,老样子...还是你自己的路径
UIUtility.AddStyleSheet(".../title-container", this, m_RootElement, m_Title, m_ContentView);
// 根据类选择器依次设置样式
this.AddToClassList("title-container");
m_RootElement.AddToClassList("root-element");
m_Title.AddToClassList("title");
m_ContentView.AddToClassList("content-view");
}
}
如何动态设置uss样式可以看我之前的一篇文章:Unity UI ToolKit 代码动态绑定样式-CSDN博客
这里UIUtility是我自己写的一个工具类,不是系统自带的。