Unity3D 游戏开发:制作游戏背包 实现拖拽物品交换数据和在地图上生成物品(30)

231 阅读1分钟

一、脚本编程

1、修改SlotUI.cs

using UnityEngine;
using UnityEngine.UI;
using TMPro;
using UnityEngine.EventSystems;

namespace MFarm.Inventory
{
    public class SlotUI : MonoBehaviour,IPointerClickHandler,IBeginDragHandler,IDragHandler,IEndDragHandler 
    {
        [Header("组件的获取")]
        [SerializeField] private Image slotImage;

        [SerializeField] private TextMeshProUGUI amountText;

        public  Image slotHightlight;

        [SerializeField] private Button button;

        [Header("格子类型")]
        public SlotType slotType;

        public bool isSelected;

        public int slotIndex;
        //物品信息
        public ItemDetails itemDetails;

        public int itemAmount; 

        private InventoryUI inventoryUI=>GetComponentInParent<InventoryUI>();

        private void Start()
        {
            isSelected = false;

            if (itemDetails.itemID == 0)
            {
                UpdateEmptySlot();
            }
        }

        //更新格子UI和信息
        public void UpdateSlot(ItemDetails item, int amount)
        {
            itemDetails = item;
            slotImage.sprite = item.itemIcon;
            itemAmount = amount;
            amountText.text = amount.ToString();
            slotImage.enabled = true;
            button.interactable = true;
        }

        //将Slot更新为空
        public void UpdateEmptySlot()
        {
            if (isSelected)
            {
                isSelected = false;
            }
            slotImage.enabled = false;
            amountText.text = string.Empty;
            button.interactable = false;
        }

        public void OnPointerClick(PointerEventData eventData)
        {
            if (itemAmount == 0) return;
            isSelected=!isSelected;
           
            inventoryUI.UpdateSlotHightlight ( slotIndex );


        }

        public void OnBeginDrag(PointerEventData eventData)
        {
            if (itemAmount != 0)
            { 
                inventoryUI.dragItem.enabled = true;
                inventoryUI.dragItem.sprite = slotImage.sprite;
                inventoryUI.dragItem.SetNativeSize();

                isSelected = true;
                inventoryUI.UpdateSlotHightlight(slotIndex);
            }
        }

        public void OnDrag(PointerEventData eventData)
        {
            inventoryUI.dragItem.transform.position=Input.mousePosition;
        }


        public void OnEndDrag(PointerEventData eventData)
        {
            inventoryUI.dragItem.enabled = false;
            // Debug.Log(eventData.pointerCurrentRaycast.gameObject);

            if (eventData.pointerCurrentRaycast.gameObject != null)
            {
                if (eventData.pointerCurrentRaycast.gameObject.GetComponent<SlotUI>() == null)
                    return;

                var targetSlot = eventData.pointerCurrentRaycast.gameObject.GetComponent<SlotUI>();
                int targetIndex = targetSlot.slotIndex;

                //在Player自身背包范围内进行交换
                if (slotType == SlotType.Bag && targetSlot.slotType == SlotType.Bag)
                {
                    InventoryManager.Instance.SwapItem(slotIndex, targetIndex);
                }
                //清空所有高亮
                inventoryUI.UpdateSlotHightlight(-1);
            }
           /* else   //测试丢在地上
            { 
                if(itemDetails.canDropped)
                {
                    //鼠标对应世界地图坐标
                    var pos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, -Camera.main.transform.position.z));

                    EventHandler.CallInstantiateItemInScene(itemDetails.itemID, pos);
                }
               
            }*/
        }
    }
}

2、修改InventoryManager.cs文件

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace MFarm.Inventory
{  
    public class InventoryManager : Singleton<InventoryManager>
    {
        [Header("物品数据")]
        public ItemDataList_SO itemDataList_SO;

        [Header("背包数据")]
        public InventoryBag_SO playerBag;


        private void Start()
        {
            EventHandler.CallUpdateInventoryUI(InventoryLocation.Player, playerBag.itemList);
        }
        public ItemDetails GetItemDetails(int ID)
        {
            return itemDataList_SO.itemDetailsList.Find(i=>i.itemID==ID);      
        }

        //添加物品
        public void AddItem( Item item ,bool toDestory)
        {
            
            int index = GetItemIndexInBag(item.itemID);//拿到物品ID或判断有没有物品

            AddItemAtIndex(item.itemID,index,1);

            Debug.Log(GetItemDetails (item.itemID).itemID +"Name:"+ GetItemDetails(item.itemID).itemName);

            if (toDestory)
            {
                Destroy(item.gameObject); 
            }

            //更新UI

            EventHandler.CallUpdateInventoryUI(InventoryLocation.Player, playerBag.itemList);
            
        }
        private bool CheckBagCapacity() //判断背包里有没有空位置
        {
            for (int i = 0; i < playerBag.itemList.Count; i++)
            {
                if (playerBag.itemList[i].itemID ==0)
                    return true ;
            }
            return false ;
        }

        private int GetItemIndexInBag(int ID)//判断背包里有没有物品
        {
            for (int i = 0; i < playerBag.itemList.Count; i++)
            {
                if (playerBag.itemList[i].itemID == ID)
                    return i;
            }
            return -1;
        }


        //在指定位置添加物品
        private void AddItemAtIndex(int ID, int index, int amount)
        {
            if (index == -1&& CheckBagCapacity()) //背包里没有物品,同时有空位
            {
                var item = new InventoryItem { itemID = ID, itemAmount = amount };

                for (int i = 0; i < playerBag.itemList.Count; i++)
                {
                    if (playerBag.itemList[i].itemID == 0)
                    { 
                        playerBag.itemList[i]= item;
                        break;
                    }
                }

            }
            else//背包有这个物品
            { 
                int currentAmount = playerBag.itemList[index].itemAmount+amount;
                var item = new InventoryItem { itemID = ID,itemAmount = currentAmount };

                playerBag.itemList[index] = item;
            }
        }
        //背包范围内交换物品
        public void SwapItem(int formIndex, int toIndex)
        { 
            InventoryItem currentItem = playerBag.itemList[formIndex];
            
            InventoryItem targeItem = playerBag.itemList[toIndex];

            if (targeItem.itemID != 0)
            {
                InventoryItem T= playerBag.itemList[formIndex];
                playerBag.itemList[formIndex] = playerBag.itemList[toIndex];
                playerBag.itemList[toIndex] = T;         
            }
            else
            {
                playerBag.itemList[toIndex] = playerBag.itemList[formIndex]; ;
                playerBag.itemList[formIndex]=new InventoryItem();
            }

            EventHandler.CallUpdateInventoryUI(InventoryLocation.Player, playerBag.itemList);
        }


    }
}
 

3、创建ItemManager.cs文件

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace MFarm.Inventory
{
    public class ItemManager : MonoBehaviour
    {
        public Item itemPrefabs;

        private Transform itemParent;

        private void OnEnable()
        {
            EventHandler.InstantiateItemInScene += InstantiateItemInScene;
        }
        private void OnDisable()
        {
            EventHandler.InstantiateItemInScene -= InstantiateItemInScene;
        }

        private void Start()
        {
            itemParent = GameObject.FindWithTag("ItemParent").transform; 
        }
        private void InstantiateItemInScene(int ID, Vector3 pos)
        {
            var item = Instantiate(itemPrefabs, pos, Quaternion.identity,itemParent);
            item.itemID = ID;
        }   
    }
}


4、编辑EventHandler.cs文件

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements.Experimental;

public static class EventHandler 
{
    public static event Action<InventoryLocation, List<InventoryItem>> UpdateInventoryUI;
    public static void CallUpdateInventoryUI(InventoryLocation location, List<InventoryItem> list)
    {
        UpdateInventoryUI?.Invoke(location, list);
    }

    public static event Action<int, Vector3> InstantiateItemInScene;
    public static void CallInstantiateItemInScene(int ID, Vector3 pos)
    {
        InstantiateItemInScene?.Invoke(ID, pos);
    }

}

二、开发操作

1、将ItemManager.cs文件赋予ItemManager文件

image.png

image.png

三、脚本逻辑

未完待续......

阅读更多作者文章:

Unity3D 游戏开发:制作游戏背包 实现物品拖拽效果(29)