目前的UI Toolkit比较适合做画面覆盖ui
暂时的缺陷如下:
教程来自b站:
阿严_独立游戏开发
本篇是笔记.
创建UIBuilder
第一种,直接在window中创建
第二种资产文件夹下创建UI document
打开后就是一样的画面,并且带着根节点
按住ctrl+alt+左键可以移动窗口(可能鼠标中键也行,但是今天我忘了带鼠标)
画布设置
不过我们不使用这个功能,手动设定窗口宽高1920*1080.
制作画面
画布已经创建好,现在开始做画面吧!效果图:
这方面就不细说了,类似安卓的前端页面,也类似web前端的操作方式,值得一提的是这里也有xml代码
创建uss(类似css)
红色框内去掉.
,添加Label,选中Label即可对所有文本的样式进行编辑.
在游戏内显示
场景内右键创建UIdocument,就会出现一个搭载ui Document脚本的对象
此处可以选展示的页面
空格显示/隐藏画面
新建脚本PartyDataScreen.cs附加到该对象上.
getcomponent获取uidocument,然后获取rootVisualElement根视觉元素,根据根视觉元素的样式是否为flex,来展示/隐藏画面.
public class PartyDataScreen : MonoBehaviour { VisualElement rootvisualElement; private void Awake() { rootvisualElement = GetComponent<UIDocument>().rootVisualElement; } private void Update() { if (Input.GetKeyDown(KeyCode.Space)) { rootvisualElement.style.display = rootvisualElement.style.display == DisplayStyle.Flex ? DisplayStyle.None : DisplayStyle.Flex; } } }
|
查找多个元素进行操作(批量操作)
rtvElement.Query()
函数可以对多个元素进行操作
public class PartyDataScreen : MonoBehaviour { VisualElement rtvElement; private void Awake() { rtvElement = GetComponent<UIDocument>().rootVisualElement; rtvElement.Query("CharacterDataPanel").ForEach(OnSelectedMultipleElements); rtvElement.Query<Label>("NameLabel").ForEach(OnSelectLabelElements); }
private void OnSelectLabelElements(Label obj) { obj.style.color = Color.red; obj.text = "冒险家"; }
private void OnSelectedMultipleElements(VisualElement obj) { obj.style.backgroundColor = Color.yellow; } }
|
查找单个元素
首先查找到索引1的个体,然后再通过q()单项设置
public class PartyDataScreen : MonoBehaviour { [SerializeField] Texture2D cat; [SerializeField] string catName; VisualElement rtvElement; private void Awake() { rtvElement = GetComponent<UIDocument>().rootVisualElement; var secondDataPanel = rtvElement.Query("CharacterDataPanel").AtIndex(1); secondDataPanel.Q<Label>().text = catName; secondDataPanel.Q("Avatar").style.backgroundImage = cat; } }
|
脚本中拖入图片素材,还有输入名字
运行结果
我们可以看到第二个框内部已更换为新的.
数据独立性
为了以后更好地维护和管理数据,我们有必要设计一个专门的类存放并处理这些数据,这也是从数据独立性方面来考虑.将游戏的逻辑和数据分开.
思路:创建一个继承于ScriptableObject的角色数据类:CharacterData,再创建四个实例分别存储四个角色数据.
创建队伍数据类,管理角色数据
角色属性类
创建白板,角色属性类CharacterStats.cs
[System.Serializable] public class CharacterStats { public int initiative; public int maxHp; public int manMp; public int attack; public int defense; }
|
创建角色数据类
创建角色数据类CharacterData.cs
详细可以看代码注释
using System.Collections; using System.Collections.Generic; using UnityEngine;
[CreateAssetMenu(menuName = ("Data/CharacterData"), fileName = ("CharacterData_"))] public class CharacterData : ScriptableObject { [SerializeField] Texture2D characterAvatarImage; [SerializeField] string characterName; [SerializeField] int characterStartLevel = 1; [SerializeField] CharacterStats characterStats;
public Texture2D CharacterAvatarImage => characterAvatarImage; public string CharacterName => characterName; public int CharacterStartLevel1 => characterStartLevel; public CharacterStats ChStats => characterStats; }
|
资源文件夹中创建CharacterData实例
所有角色实例
队伍数据类
创建队伍数据类PartyData.cs
using System.Collections; using System.Collections.Generic; using UnityEngine;
[CreateAssetMenu(menuName = ("Data/PartyData"), fileName = ("PartyData_"))] public class PartyData : ScriptableObject { [SerializeField] List<CharacterData> characterDataList; public List<CharacterData> CharacterDataList => characterDataList; }
|
拖入角色实例,这样队伍里增加减少或角色更加方便.
这样,就可以通过序列化PartyData对象获取整个队伍的数据.
CustomControls自定义控件
CustomControls是ui Toolkit的一个高级功能,我们可以通过c#脚本创建拥有自定义逻辑的复杂ui元素,自定义控件的创建从相应的c#类开始
实时生成角色数据面板
创建CharacterDataPanel角色数据面板类
using UnityEngine.UIElements; public class CharacterDataPanel : VisualElement { public new class UxmlFactory : UxmlFactory<CharacterDataPanel> { } public CharacterDataPanel() { } }
|
保存后打开UI Builder,在下面project中可以找到该控件
给自定义控件添加内容
使用UI Toolkit的Template模板功能.
创建模板
将模板存放到Assets\Data\UIDocuments\Resources
中,注意Resources
文件夹创建的时候不可以有任何大小写拼写错误.
控件显示如下图
显示成这个样子是因为创建的控件自动多了一个容器
我们在存放目录这,右键从UIBuilder打开模板的uxml文件
重置basis属性,grow设为1
然后保存后回到主页面,将basis设为25%
全部替换掉,就得到了原来的样子
现在,我们有了数据面板的模板,那么接下来实现用c#脚本生成模板
代码生成模板
打开CharacterDataPanel.cs
using UnityEngine; using UnityEngine.UIElements; public class CharacterDataPanel : VisualElement { readonly TemplateContainer templateContainer; public new class UxmlFactory : UxmlFactory<CharacterDataPanel> { }
public CharacterDataPanel() { templateContainer = Resources.Load<VisualTreeAsset>("CharacterDataPanel").Instantiate(); templateContainer.style.flexGrow = 1.0f; hierarchy.Add(templateContainer); } }
|