一、 效果展示
二、 源代码
1,ItemManager.cs
//逻辑简介:该脚本作用是生成背包格子和加载背包物品,获得被拖拽物品和目标物品
//配置:1,需要Scroll View来存放背包物品。
//2,将要作为模板的物品名字更改为EquipSlotTemplate。using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;public class ItemManager : MonoBehaviour
{[SerializeField] private GameObject currentObject;GameObject EquipSlotTemplate;public static ItemManager instance;Transform content;public GameObject nowItem;public GameObject toItem;public List<Item> itemsList = new List<Item>();//public Dictionary<string, Item> itemsDic = new Dictionary<string, Item>();public Dictionary<int,GameObject> grid=new Dictionary<int,GameObject>();AmourTable amourTable;WeaponTable weaponTable;private void Awake(){amourTable = Resources.Load<AmourTable>("TableData/AmourTable");weaponTable = Resources.Load<WeaponTable>("TableData/WeaponTable");AddItem(amourTable.DataList[0]);//添加装备AddItem(amourTable.DataList[1]);AddItem(amourTable.DataList[2]);AddItem(amourTable.DataList[3]);AddItem(amourTable.DataList[0]);AddItem(amourTable.DataList[0]);AddItem(amourTable.DataList[0]);AddItem(weaponTable.DataList[0]);content = GameObject.Find("Item_Content").transform;EquipSlotTemplate = GameObject.Find("EquipSlotTemplate");if (instance == null){instance = this;}else{Destroy(gameObject);}}private void Start(){int rowCount = 0;int columnCount = 0;float xOffset = 173f;float yOffset = -127f;//生成格子for (int i = 0; i < 20; i++){GameObject equipSlot = Instantiate(EquipSlotTemplate);equipSlot.transform.SetParent(content, false);RectTransform rectTransform = equipSlot.GetComponent<RectTransform>();rectTransform.anchoredPosition = new Vector2(columnCount * xOffset-180f, rowCount * yOffset+82f);columnCount++;if (columnCount >= 3){columnCount = 0;rowCount++;}if (equipSlot.GetComponent<BaseItem>() == null){equipSlot.AddComponent<BaseItem>();}grid.Add(i, equipSlot);}UpdateItem();}private void AddItem(Item item){itemsList.Add(item);}int index = 0;public void UpdateItem(){ //遍历背包物品字典,将背包物品以此赋给格子。foreach (var item in itemsList){grid[index].GetComponent<Image>().sprite = item.sprite;grid[index].GetComponent<BaseItem>().item = item;index++;if (index >= grid.Count){break;}}}}
2,BaseItem.cs
//逻辑简介:拖拽物品时,记录被拖拽物品的初始父物体,被拖拽物品先作为canvas的子物体,拖拽成功后,让被拖拽物品的父物体为目标物体的父物体,目标物体的父物体成为被拖拽物品的的父物体。然后再交换位置。
//配置:1,把Canvas的名称改为StaticCanvas,若不更改的话,需要修改代码canvas = GameObject.Find("StaticCanvas").GetComponent<Canvas>();
//2,所有装备槽有一个父物体。名字为“EquipSlots”。每个装备槽根据类型也要改名为“Head_Slot”等等。背包槽的父物体也要改名为“Item_Content”。
//3,该脚本通过ItemManager挂载到每个物品上。using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;public class BaseItem :MonoBehaviour,IPointerEnterHandler, IPointerExitHandler, IDragHandler, IBeginDragHandler, IEndDragHandler
{[SerializeField] private GameObject currentObject;RectTransform rectTransform;Canvas canvas;Transform canvasTranform; // 作为临时父级容器,用于装载和移除拖动的图像Transform currentParentTrans;[SerializeField] Transform itemParentTrans; // 作为临时父级容器,用于装载和移除拖动的图像Image image;public bool hasEquipSlot;Vector2 currentRectTrans;[SerializeField] public Item item;private void Awake() {canvas = GameObject.Find("StaticCanvas").GetComponent<Canvas>();canvasTranform = GameObject.Find("StaticCanvas").transform;rectTransform = GetComponent<RectTransform>();image = GetComponent<Image>();if (item == null){item = new Item();}}private void Start() {if (transform.name == "Head_Slot")//给装备槽 加type{item.type = "头盔";}else if (transform.name == "Clothe_Slot"){item.type = "衣服";}else if (transform.name == "Wrist_Slot"){item.type = "手腕";}else if (transform.name == "Shoes_Slot"){item.type = "鞋子";}else if (transform.name == "Horse_Slot"){item.type = "马匹";}else if (transform.name == "Wepon_Slot"){ item.type = "武器";}currentParentTrans = transform.parent;}public void OnPointerEnter(PointerEventData eventData){currentObject = eventData.pointerEnter;ItemManager.instance.toItem = gameObject;}public void OnPointerExit(PointerEventData eventData){ItemManager.instance.toItem = null;}public void OnBeginDrag(PointerEventData eventData){if (item.name == null){return;}currentRectTrans = rectTransform.anchoredPosition;currentParentTrans = transform.parent;ItemManager.instance.nowItem = gameObject;ItemManager.instance.toItem = null;itemParentTrans = currentObject.transform.parent; //记录当前物体的父物体位置currentObject.transform.SetParent(canvasTranform); //将当前物体移动到临时父级容器}public void OnDrag(PointerEventData eventData){if (item.name == null){return;}transform.GetComponent<Button>().interactable = false;image.raycastTarget = false;// 根据鼠标的移动来调整物体的位置rectTransform.anchoredPosition += eventData.delta / canvas.scaleFactor;}public void OnEndDrag(PointerEventData eventData){if (item.name == null){return;}Debug.Log(item.sprite);if (ItemManager.instance.toItem == null) //物品栏装备没有拖动到 装备栏和物品栏 即toItem为null {currentObject.transform.SetParent(itemParentTrans);// 将当前物体的位置重置为原始位置rectTransform.anchoredPosition = currentRectTrans;}else if (ItemManager.instance.toItem.transform.parent.name == "EquipSlots"&¤tParentTrans.name=="Item_Content") //物品栏装备拖动到到了装备槽上{//type判断if (ItemManager.instance.nowItem.GetComponent<BaseItem>().item.type == ItemManager.instance.toItem.GetComponent<BaseItem>().item.type){//父类交换ItemManager.instance.nowItem.transform.SetParent(ItemManager.instance.toItem.transform.parent, false);//把这个物体作为装备槽父物体的子物体。ItemManager.instance.toItem.transform.SetParent(currentParentTrans, false);//位置交换Vector2 temp = ItemManager.instance.toItem.GetComponent<RectTransform>().anchoredPosition;//获得装备槽本地坐标ItemManager.instance.toItem.GetComponent<RectTransform>().anchoredPosition = currentRectTrans;ItemManager.instance.nowItem.GetComponent<RectTransform>().anchoredPosition = temp;//把装备槽本地坐标赋值给该物体。}else {currentObject.transform.SetParent(itemParentTrans);rectTransform.anchoredPosition = currentRectTrans;}}else if (currentParentTrans.name=="EquipSlots"&&ItemManager.instance.toItem.transform.parent.name=="Item_Content")//装备栏移动到物品栏 {//判断type是否相同 相同交换位置 或者 不同(装备和格子)也交换位置。if ((ItemManager.instance.nowItem.GetComponent<BaseItem>().item.type == ItemManager.instance.toItem.GetComponent<BaseItem>().item.type) || ItemManager.instance.toItem.GetComponent<BaseItem>().item.name == null){//父类交换ItemManager.instance.nowItem.transform.SetParent(ItemManager.instance.toItem.transform.parent, false);ItemManager.instance.toItem.transform.SetParent(currentParentTrans, false);//位置交换Vector2 temp = currentRectTrans;ItemManager.instance.nowItem.GetComponent<RectTransform>().anchoredPosition = ItemManager.instance.toItem.GetComponent<RectTransform>().anchoredPosition;ItemManager.instance.toItem.GetComponent<RectTransform>().anchoredPosition = temp;ItemManager.instance.nowItem.GetComponent<BaseItem>().item.type = ItemManager.instance.toItem.GetComponent<BaseItem>().item.type;}else{ currentObject.transform.SetParent(itemParentTrans);rectTransform.anchoredPosition = currentRectTrans;}}//物品栏物品相互更换位置else if (ItemManager.instance.toItem.transform.parent.name == "Item_Content" && currentParentTrans.name == "Item_Content")//{//父类交换ItemManager.instance.toItem.transform.SetParent(currentParentTrans);ItemManager.instance.nowItem.transform.SetParent(currentParentTrans);//位置交换Vector2 temp = currentRectTrans;ItemManager.instance.nowItem.GetComponent<RectTransform>().anchoredPosition = ItemManager.instance.toItem.GetComponent<RectTransform>().anchoredPosition;ItemManager.instance.toItem.GetComponent<RectTransform>().anchoredPosition = temp;}//装备栏之间交换位置else if (ItemManager.instance.toItem.transform.parent.name == "EquipSlots" && currentParentTrans.name == "EquipSlots"){if (ItemManager.instance.nowItem.GetComponent<BaseItem>().item.type == ItemManager.instance.toItem.GetComponent<BaseItem>().item.type){//父类交换ItemManager.instance.toItem.transform.SetParent(currentParentTrans);ItemManager.instance.nowItem.transform.SetParent(currentParentTrans);//位置交换Vector2 temp = currentRectTrans;//获得nowItem本地坐标ItemManager.instance.nowItem.GetComponent<RectTransform>().anchoredPosition = ItemManager.instance.toItem.GetComponent<RectTransform>().anchoredPosition;ItemManager.instance.toItem.GetComponent<RectTransform>().anchoredPosition = temp;}else {currentObject.transform.SetParent(itemParentTrans);rectTransform.anchoredPosition = currentRectTrans;}}// 恢复鼠标点击transform.GetComponent<Button>().interactable = true;image.raycastTarget = true;ItemManager.instance.nowItem = null;ItemManager.instance.toItem = null;}}
public class Item
{public int id;public string name;public Sprite sprite;public int price;public string type;
}
3,加载资源
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(menuName = "Data/AmourTable", fileName = "AmourTable")]public class AmourTable : ScriptableObject
{public List<AmourTableItem> DataList = new List<AmourTableItem>();public Dictionary<string, AmourTableItem> WeaponDataList = new Dictionary<string, AmourTableItem>();
}
[System.Serializable]public class AmourTableItem:Item
{public int weight;public int defense;}
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
[CreateAssetMenu(menuName = "Data/ItemTable", fileName = "ItemTable")]public class ItemTable : ScriptableObject
{public List<ItemTableItem> DataList = new List<ItemTableItem>();public Dictionary<string, ItemTableItem> ItemDataList = new Dictionary<string, ItemTableItem>();
}
[System.Serializable]public class ItemTableItem:Item
{public int Price;public int weight;}