Unity3D 游戏开发:背包数据界面 创建按钮的添加和删除数据功能(17)

1,112 阅读4分钟

一、用户编程

1、实现两个按钮的添加和删除功能

image.png

image.png image.png

using UnityEditor;
using UnityEditor.UIElements;
using UnityEngine;
using UnityEngine.UIElements;
using System.Collections.Generic;
using System;
using System.Linq;

public class ItemEditor : EditorWindow 
{
    private ItemDataList_SO dataBase;

    private List<ItemDetails> itemList  = new List<ItemDetails>();

    private VisualTreeAsset itemRowTemplate;

    private ScrollView itemDetailsSection;

    private ItemDetails activeItem;

    //默认浏览图片
    private Sprite defultIcon;

    private VisualElement iconPreview;
    //获得Visual Element 
    private ListView itemlistView;

    [MenuItem("Lzj/ItemEditor")] 
    public static void ShowExample()
    {
        ItemEditor wnd = GetWindow<ItemEditor>();
        wnd.titleContent = new GUIContent("ItemEditor");
    }

    public void CreateGUI()
    {
        // Each editor window contains a root VisualElement object
        VisualElement root = rootVisualElement;

       // 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/ItemRowTemplates.uxml");

        //拿到默认Icon图片
        defultIcon = AssetDatabase.LoadAssetAtPath<Sprite>("Assets/M Studio/Art/Items/Icons/Lzj.jpg");

        //变量赋值,获得控制权
        itemlistView = root.Q<VisualElement>("ItemList").Q<ListView>("ListView");
        itemDetailsSection = root.Q <ScrollView>("ItemDetails");
        iconPreview = itemDetailsSection.Q<VisualElement>("Icon");

        //获得Button
        root.Q<Button>("AddButton").clicked += OnAddItemCliked;
        root.Q<Button>("DeleteButton").clicked += OnDeleteItemCliked;
        //加载数据
        LoadDataBase();

        //生成ListView
        GenerateListView(); 

    }

    # region 按键事件
    private void OnDeleteItemCliked()
    {
        itemList.Remove(activeItem);
        itemlistView.Rebuild();
        itemDetailsSection.visible =false;
    }

    private void OnAddItemCliked()
    {
        ItemDetails newItem = new ItemDetails();
        newItem.itemName = "NEW NAME";
        newItem .itemID =1000+itemList.Count;
        itemList .Add(newItem);
        itemlistView.Rebuild();

    }
    #endregion 

    private void LoadDataBase()
    {
        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.itemDataList;

        EditorUtility.SetDirty(dataBase);

        //Debug.Log (itemList[0].itemID); 
    }
    private void GenerateListView()
    { 
        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 += OnListSelectionChane;
        //右侧信息不可见
        itemDetailsSection.visible= false;
    }

    private void OnListSelectionChane(IEnumerable<object> selectedItem)
    {
        activeItem=(ItemDetails)selectedItem.First();
        GetItemDetails();
        itemDetailsSection.visible = true;
    }

    private void GetItemDetails()
    {
        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();
        });

        itemDetailsSection.Q<EnumField>("ItemType").value = activeItem.itemType;
        itemDetailsSection.Q<EnumField>("ItemType").RegisterValueChangedCallback(evt =>
        {
            activeItem.itemType = (ItemType)Enum.Parse(typeof(ItemType), evt.newValue.ToString());
        });

        iconPreview.style.backgroundImage = activeItem.itemIcon == null ? defultIcon.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 ?defultIcon.texture: newIcon.texture;
            itemlistView.Rebuild();
        });

        itemDetailsSection.Q<ObjectField>("ItemSprite").value = activeItem.itemOnWorldSprite;
        itemDetailsSection.Q<ObjectField>("ItemSprite").RegisterValueChangedCallback(evt =>
        {
            Sprite newIcon = evt.newValue as Sprite;
            activeItem.itemOnWorldSprite = newIcon;
        });

        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>("CanPickup").value = activeItem.canPickup;
        itemDetailsSection.Q<Toggle>("CanPickup").RegisterValueChangedCallback(evt=>
        { 
            activeItem.canPickup=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;
        });
    } 
} 

二、初步了解脚本编程

1、获得Button

    root.Q<Button>("AddButton").clicked += OnAddItemCliked;
    root.Q<Button>("DeleteButton").clicked += OnDeleteItemCliked;
    

1)、代码是在UI界面中找到名为"AddButton"的Button控件,并注册了一个点击事件OnAddItemCliked。当用户点击该按钮时,会触发OnAddItemCliked()方法。这个方法实现了添加新条目的逻辑

2)、在这里,clicked是一个Unity UIElements中的事件(event),用于表示当该元素被点击时触发的事件,类似于一些其他UI框架中的Click()方法。

3)、使用+=操作符,我们将OnAddItemCliked()方法与Button的clicked事件绑定起来了。这意味着,当该Button被点击时,就会调用OnAddItemCliked()方法。

2、添加按键事件

private void OnDeleteItemCliked()
{
    itemList.Remove(activeItem);
    itemlistView.Rebuild();
    itemDetailsSection.visible =false;
}

private void OnAddItemCliked()
{
    ItemDetails newItem = new ItemDetails();
    newItem.itemName = "NEW NAME";
    newItem .itemID =1000+itemList.Count;
    itemList .Add(newItem);
    itemlistView.Rebuild();

}

1)、itemList.Remove(activeItem):

这行代码的作用是从itemList列表中移除activeItem对象。在代码里,activeItem是当前被选择的ItemDetails对象。

当用户点击UI界面中的"DeleteButton"按钮时,就会触发该代码。在删除前,我们需要将该对象从列表中移除,并更新ListView。

2)、itemDetailsSection.visible =false:

itemDetailsSection是一个Unity UIElements中的ScrollView对象,用于展示当前选择的ItemDetails对象的详细信息。当用户没有选择任何ItemDetails对象时,我们希望这个ScrollView不可见,以避免UI界面上的一些不必要的干扰。这时就会使用到这行代码。

具体地说,visible是一个属性(property),它控制对象是否可见。通过将visible属性设置为false,我们可以让itemDetailsSection在UI界面上不可见,从而达到隐藏的效果。

3)ItemDetails newItem = new ItemDetails():

这行代码的作用是创建一个新的ItemDetails对象,并将其赋值给变量newItem。在代码中,ItemDetails是一个自定义的类,用于存储游戏物品的详细信息,比如名称、图标、类型等等。

当用户点击UI界面中的"AddButton"按钮时,就会触发该代码。我们需要添加一个新的ItemDetails对象到itemList列表中,以实现添加新条目的功能。

4)、itemList.Count

itemList.Count表示itemList这个列表中元素的数量,即列表中包含多少个元素。

在代码中,我们使用了这行代码来获取itemList列表的长度。目的是在UI界面中更新列表的显示,以展示最新的信息。具体而言,我们需要确保ListView包含与itemList中相同数量的子元素,以便正确地显示所有的游戏物品详细信息。

5)、itemList .Add(newItem):

itemList.Add(newItem)是将一个新的ItemDetails对象添加到itemList列表中去。在代码中,newItem是我们创建的新对象,它包含了一个游戏物品的详细信息。

当我们想要在UI界面中添加一个新的游戏物品时,就需要使用这行代码。它会将新游戏物品的详细信息添加到itemList列表中去,以便能在ListView中正确地显示出来。

三、未完待续......

阅读更多作者文章:

Unity3D 游戏开发:用户界面(Editor)绑定Editor Windows中的参数变量(16)