UI Toolkit
此文章用于学习UnityUI系统,手头的项目做完会来完善
官方文档
Unity上方菜单栏点击Window->UI Toolkit->Samples可以看UI Toolkit中的很多样例
使用 UI Toolkit 和 UI Builder 制作物品编辑器
在文件夹中右键->Create->UI Toolkit->Editor Window
出现以下窗口
输入名字创建窗口
文件夹中出现三个文件
从这步开始就能点击Unity上方菜单栏召唤自己写的Editor Window了
点击ItemEditor进入UIBuilder,用里面的工具创建需要的UI面板
创建 ListView 中的 ItemTemplate
再创建一个UIDocument,作为ItemList中每一个物体显示的模板
生成 ListView 列表
实现ItemTemplate读取数据库中物品数据并将其呈现在ListView上的方法
publicclassItemEditor:EditorWindow{private ItemDataList_SO dataBase;private List<ItemDetails> itemList =newList<ItemDetails>();private VisualTreeAsset itemRowTemplate;private ListView itemListView;[MenuItem("Editor/ItemEditor")]publicstaticvoidShowExample(){
ItemEditor wnd =GetWindow<ItemEditor>();
wnd.titleContent =newGUIContent("ItemEditor");}publicvoidCreateGUI(){
VisualElement root = rootVisualElement;
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/UIBuilder/ItemEditor.uxml");
VisualElement labelFromUXML = visualTree.Instantiate();
root.Add(labelFromUXML);//拿到模板数据
itemRowTemplate =
AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/UIBuilder/ItemRowTemplate.uxml");//变量赋值
itemListView = root.Q<VisualElement>("ItemList").Q<ListView>("ListView");LoadDataBase();GenerateListView();}/// <summary>/// 从数据库中加载文件/// </summary>privatevoidLoadDataBase(){
var dataArray=AssetDatabase.FindAssets("ItemDataList_SO");if(dataArray.Length >1){
var path = AssetDatabase.GUIDToAssetPath(dataArray[0]);//找到文件中对应的路径
dataBase = AssetDatabase.LoadAssetAtPath(path,typeof(ItemDataList_SO)) as ItemDataList_SO;}
itemList = dataBase.itemDetailsList;//如果不标记则无法保存数据
EditorUtility.SetDirty(dataBase);}privatevoidGenerateListView(){
Func<VisualElement> makeItem =()=> itemRowTemplate.CloneTree();//创建
Action<VisualElement,int> bindItem =(e, i)=>{//在ItemTemplate上绑定数据if(i < itemList.Count){if(itemList[i].itemIcon != null){
e.Q<VisualElement>("Icon").style.backgroundImage = itemList[i].itemIcon.texture;}
e.Q<Label>("Name").text = itemList[i]== null ?"NO ITEM": itemList[i].itemName;}};//将ItemTemplate呈现在ListView里
itemListView.fixedItemHeight =60;
itemListView.itemsSource = itemList;
itemListView.makeItem = makeItem;
itemListView.bindItem = bindItem;}}
makeItem会在每次添加新物品时调用——在数据绘制到窗口时会根据数据的数目逐一增加一个Item的时候
bindItem每个窗口显示的具体内容
itemsSource对应itemList里面的每一个数据
绑定 Editor Window 中的参数变量,实现 ListView 添加删除同步信息功能
实现在右侧面板中显示物体对应的信息
publicclassItemEditor:EditorWindow{private ItemDataList_SO dataBase;private List<ItemDetails> itemList =newList<ItemDetails>();private VisualTreeAsset itemRowTemplate;private ScrollView itemDetailsSection;private ItemDetails activeItem;//默认预览图片private Sprite defaultIcon;private VisualElement iconPreview;//获得VisualElementprivate ListView itemListView;[MenuItem("M STUDIO/ItemEditor")]publicstaticvoidShowExample(){
ItemEditor wnd =GetWindow<ItemEditor>();
wnd.titleContent =newGUIContent("ItemEditor");}publicvoidCreateGUI(){// Each editor window contains a root VisualElement object
VisualElement root = rootVisualElement;// VisualElements objects can contain other VisualElement following a tree hierarchy.// VisualElement label = new Label("Hello World! From C#");// root.Add(label);// Import UXML
var visualTree = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/UI Builder/ItemEditor.uxml");
VisualElement labelFromUXML = visualTree.Instantiate();
root.Add(labelFromUXML);//拿到模版数据
itemRowTemplate = AssetDatabase.LoadAssetAtPath<VisualTreeAsset>("Assets/Editor/UI Builder/ItemRowTemplate.uxml");//拿默认Icon图片
defaultIcon = AssetDatabase.LoadAssetAtPath<Sprite>("Assets/M Studio/Art/Items/Icons/icon_M.png");//变量赋值
itemListView = root.Q<VisualElement>("ItemList").Q<ListView>("ListView");
itemDetailsSection = root.Q<ScrollView>("ItemDetails");
iconPreview = itemDetailsSection.Q<VisualElement>("Icon");//获得按键
root.Q<Button>("AddButton").clicked += OnAddItemClicked;
root.Q<Button>("DeleteButton").clicked += OnDeleteClicked;//加载数据LoadDataBase();//生成ListViewGenerateListView();}#region按键事件privatevoidOnDeleteClicked(){
itemList.Remove(activeItem);
itemListView.Rebuild();
itemDetailsSection.visible =false;}privatevoidOnAddItemClicked(){
ItemDetails newItem =newItemDetails();
newItem.itemName ="NEW ITEM";
newItem.itemID =1001+ itemList.Count;
itemList.Add(newItem);
itemListView.Rebuild();}#endregionprivatevoidLoadDataBase(){
var dataArray = AssetDatabase.FindAssets("ItemDataList_SO");//var dataArray = AssetDatabase.FindAssets("t:ItemDataList_SO"); //不同版本写法不一样//if (dataArray.Length >= 1) //不同版本写法不同if(dataArray.Length >1){
var path = AssetDatabase.GUIDToAssetPath(dataArray[0]);
dataBase = AssetDatabase.LoadAssetAtPath(path,typeof(ItemDataList_SO)) as ItemDataList_SO;}
itemList = dataBase.itemDetailsList;//如果不标记则无法保存数据
EditorUtility.SetDirty(dataBase);// Debug.Log(itemList[0].itemID);}privatevoidGenerateListView(){
Func<VisualElement> makeItem =()=> itemRowTemplate.CloneTree();
Action<VisualElement,int> bindItem =(e, i)=>{if(i < itemList.Count){if(itemList[i].itemIcon != null)
e.Q<VisualElement>("Icon").style.backgroundImage = itemList[i].itemIcon.texture;
e.Q<Label>("Name").text = itemList[i]== null ?"NO ITEM": itemList[i].itemName;}};
itemListView.fixedItemHeight =50;//根据需要高度调整数值
itemListView.itemsSource = itemList;
itemListView.makeItem = makeItem;
itemListView.bindItem = bindItem;
itemListView.onSelectionChange += OnListSelectionChange;//右侧信息面板不可见
itemDetailsSection.visible =false;}privatevoidOnListSelectionChange(IEnumerable<object> selectedItem){
activeItem =(ItemDetails)selectedItem.First();GetItemDetails();
itemDetailsSection.visible =true;}privatevoidGetItemDetails(){
itemDetailsSection.MarkDirtyRepaint();
itemDetailsSection.Q<IntegerField>("ItemID").value = activeItem.itemID;
itemDetailsSection.Q<IntegerField>("ItemID").RegisterValueChangedCallback(evt =>{
activeItem.itemID = evt.newValue;});
itemDetailsSection.Q<TextField>("ItemName").value = activeItem.itemName;
itemDetailsSection.Q<TextField>("ItemName").RegisterValueChangedCallback(evt =>{
activeItem.itemName = evt.newValue;
itemListView.Rebuild();});
iconPreview.style.backgroundImage = activeItem.itemIcon == null ? defaultIcon.texture : activeItem.itemIcon.texture;
itemDetailsSection.Q<ObjectField>("ItemIcon").value = activeItem.itemIcon;
itemDetailsSection.Q<ObjectField>("ItemIcon").RegisterValueChangedCallback(evt =>{
Sprite newIcon = evt.newValue as Sprite;
activeItem.itemIcon = newIcon;
iconPreview.style.backgroundImage = newIcon == null ? defaultIcon.texture : newIcon.texture;
itemListView.Rebuild();});//其他所有变量的绑定
itemDetailsSection.Q<ObjectField>("ItemSprite").value = activeItem.itemOnWorldSprite;
itemDetailsSection.Q<ObjectField>("ItemSprite").RegisterValueChangedCallback(evt =>{
activeItem.itemOnWorldSprite =(Sprite)evt.newValue;});
itemDetailsSection.Q<EnumField>("ItemType").Init(activeItem.itemType);
itemDetailsSection.Q<EnumField>("ItemType").value = activeItem.itemType;
itemDetailsSection.Q<EnumField>("ItemType").RegisterValueChangedCallback(evt =>{
activeItem.itemType =(ItemType)evt.newValue;});
itemDetailsSection.Q<TextField>("Description").value = activeItem.itemDescription;
itemDetailsSection.Q<TextField>("Description").RegisterValueChangedCallback(evt =>{
activeItem.itemDescription = evt.newValue;});
itemDetailsSection.Q<IntegerField>("ItemUseRadius").value = activeItem.itemUseRadius;
itemDetailsSection.Q<IntegerField>("ItemUseRadius").RegisterValueChangedCallback(evt =>{
activeItem.itemUseRadius = evt.newValue;});
itemDetailsSection.Q<Toggle>("CanPickedup").value = activeItem.canPickedup;
itemDetailsSection.Q<Toggle>("CanPickedup").RegisterValueChangedCallback(evt =>{
activeItem.canPickedup = evt.newValue;});
itemDetailsSection.Q<Toggle>("CanDropped").value = activeItem.canDropped;
itemDetailsSection.Q<Toggle>("CanDropped").RegisterValueChangedCallback(evt =>{
activeItem.canDropped = evt.newValue;});
itemDetailsSection.Q<Toggle>("CanCarried").value = activeItem.canCarried;
itemDetailsSection.Q<Toggle>("CanCarried").RegisterValueChangedCallback(evt =>{
activeItem.canCarried = evt.newValue;});
itemDetailsSection.Q<IntegerField>("Price").value = activeItem.itemPrice;
itemDetailsSection.Q<IntegerField>("Price").RegisterValueChangedCallback(evt =>{
activeItem.itemPrice = evt.newValue;});
itemDetailsSection.Q<Slider>("SellPercentage").value = activeItem.sellPercentage;
itemDetailsSection.Q<Slider>("SellPercentage").RegisterValueChangedCallback(evt =>{
activeItem.sellPercentage = evt.newValue;});}}
版权归原作者 Petrichorzncu 所有, 如有侵权,请联系我们删除。