米娜桑扩你急哇,大家好久不见,由于最近一直在忙活比赛的项目,什么画画啊写代码啊一直都没时间跟大伙更新一期视频,今天就来点大家想看的东西,我们来实现背包系统中物品的拾取拖拽掉落还有换位置。
学习目标:
首先学习之前所需要的必备知识有:ScriptableObject,数据结构链表的使用,以及一些涉及到UnityEditor相关便于我们开发的,射线相关的UI以及EventSystems的命名空间,那么现在就开始吧。
学习内容:
首先我们需要整体的对物品进行一个描述,如它是什么类型的,是可以浇花的,还是可以种地的,还是可以攻击的,我们将在一个只用来写枚举的C#脚本中创建它,
public enum ItemType
{
Seed,
Commodity,
Watering_tool,
Hoeing_tool,
Chopping_tool,
Breaking_tool,
Reping_tool,
Collecting_tool,
Reapable_scenery,
Furinture,
None,
Count,
}
只有枚举没有类名,
首先我们先写展现Item细节类的脚本ItemDetails,我们使用
[System.Serializable]让它即使不能被挂载到游戏对象上,也能被其它类识别然后调用,
using UnityEngine;
[System.Serializable]
public class ItemDetails
{
public int itemCode;
public ItemType itemType;
public string itemDescription;
public Sprite itemSprite;
public string itemLongDescription;
public short itemUseGridRadius;
public float itemUseRadius;
public bool isStartingItem;
public bool canBePickUp;
public bool canBeDropped;
public bool canBeEaten;
public bool canBeCarried;
}
然后我们就可以开始写Item类了,(这里[ItemCodeDescription]需要自定义的,一会讲)ItemCode属性是非常重要的东西,每一个独一无二的Item都将拥有属于自己ItemCode,然后我们就可以在ItemCode中调用它
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Item : MonoBehaviour
{
[ItemCodeDescription][SerializeField] private int _itemCode;
private SpriteRenderer spriteRenderer;
public int ItemCode
{
get
{
return _itemCode;
}
set
{
_itemCode = value;
}
}
private void Awake()
{
spriteRenderer = GetComponentInChildren<SpriteRenderer>();
}
private void Start()
{
if(ItemCode != 0)
{
Init(ItemCode);
}
}
public void Init(int itemCodeParams)
{
}
}
(这里[ItemCodeDescription]需要自定义的,一会讲)
弄完后我们需要一个链表数组来存储所有的Item
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "so_Itemlist", menuName = "Scriptable Objects/Item list")]
public class SO_ItemList : ScriptableObject
{
public List<ItemDetails> itemDetails;
}
回到Unity,我们为每一个Item创建独一无二的数据,这里就根据你的需求来填写这些数据了。
那么这个 iItemCodeDescription是从哪里来的呢,这里就设计到我们的UnityEditor知识了。
在你的脚本文件夹中创建两个如下名字的脚本
先 打开Attribute,我们只需要让它继承PropertyAttribute即可
using UnityEngine;
public class ItemCodeDescriptionAttribute : PropertyAttribute
{
}
剩下的脚本则需要引用UnityEditor命名空间,我们将在GUI上更改信息
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(ItemCodeDescriptionAttribute))] //告诉系统自定义特性名叫ItemCodeDescriptionAttribute
public class ItemCodeDescriptionDrawer : PropertyDrawer
{
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUI.GetPropertyHeight(property) * 2;
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
EditorGUI.BeginProperty(position, label, property);
if(property.propertyType == SerializedPropertyType.Integer)
{
EditorGUI.BeginChangeCheck();
var newValue = EditorGUI.IntField(new Rect(position.x, position.y, position.width, position.height / 2),label,property.intValue);
EditorGUI.LabelField(new Rect(position.x, position.y + position.height /2 , position.width, position.height / 2), "Item Description",
GetItemDescription(property.intValue));
//如果Item的ItemCode的值发生改变,则面板上的值也要发生变化
if (EditorGUI.EndChangeCheck())
{
property.intValue = newValue;
}
}
EditorGUI.EndProperty();
}
private string GetItemDescription(int itemCode)
{
SO_ItemList so_itemList;
so_itemList = AssetDatabase.LoadAssetAtPath("Assets/Scriptable Object Assets/Items/so_Itemlist.asset", typeof(SO_ItemList)) as SO_ItemList;
List<ItemDetails> itemDetailLists = so_itemList.itemDetails;
ItemDetails itemDetail = itemDetailLists.Find(x => x.itemCode == itemCode);
if(itemDetail!= null)
{
return itemDetail.itemDescription;
}
else
{
return "";
}
}
}
我们会用到链表系统SO_ItmeList,并且用 AssetDatabase.LoadAssetAtPath获取本地路径,找到SO_ItmeList里面所有的链表,然后用Find函数寻找相同itemCode的ItemDetails,如果找到了就返回它的描述字符串,否则返回空双引号"";
接下来就可以用你自定义的特性了
接下来我们创建一个父预制体,如下所示添加Item类,
把Item做成预制体后创建它的子对象操作如下
比如我做了一个南瓜Item,可以看到,我们给南瓜对应的编号,底下的Decsription就会跟着改变,我是10001,描述的内容就是南瓜
我们可以添加一些效果给场景中的Item类,例如有些Item的属性中是不能被拾取,例如这些草仅仅是风景用途
我们可以让在经过草的时候摆动一下。
写个新脚本用协程来实现
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemNudge : MonoBehaviour
{
[SerializeField] private float pauseTime = 0.04f;
private WaitForSeconds pause;
private bool isAnimating = false;
private void Awake()
{
pause = new WaitForSeconds(pauseTime);
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (!isAnimating)
{
if(gameObject.transform.position.x < collision.transform.position.x) //如果在左边
{
StartCoroutine(nameof(RotateAndClock));
}
else
{
StartCoroutine(nameof(RotateClock));
}
}
}
private IEnumerator RotateAndClock()
{
isAnimating = true;
for (int i = 0; i < 4; i++)
{
gameObject.transform.GetChild(0).Rotate(0f, 0f, 2f);
yield return pause;
}
for (int i = 0; i < 5; i++)
{
gameObject.transform.GetChild(0).Rotate(0f, 0f, -2f);
yield return pause;
}
gameObject.transform.GetChild(0).Rotate(0f, 0f, 2f);
yield return pause;
isAnimating = false;
}
private IEnumerator RotateClock()
{
isAnimating = true;
for (int i = 0; i < 4; i++)
{
gameObject.transform.GetChild(0).Rotate(0f, 0f, -2f);
yield return pause;
}
for (int i = 0; i < 5; i++)
{
gameObject.transform.GetChild(0).Rotate(0f, 0f, 2f);
yield return pause;
}
gameObject.transform.GetChild(0).Rotate(0f, 0f, -2f);
yield return pause;
isAnimating = false;
}
}
再回到Item类在初始化方法中判断是不是ItemType.Reapable_scenery,是的话就给它添加我们刚刚新建的脚本
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Item : MonoBehaviour
{
[ItemCodeDescription][SerializeField] private int _itemCode;
private SpriteRenderer spriteRenderer;
public int ItemCode
{
get
{
return _itemCode;
}
set
{
_itemCode = value;
}
}
private void Awake()
{
spriteRenderer = GetComponentInChildren<SpriteRenderer>();
}
private void Start()
{
if(ItemCode != 0)
{
Init(ItemCode);
}
}
public void Init(int itemCodeParams)
{
if(itemCodeParams != 0)
{
ItemCode = itemCodeParams;
ItemDetails itemDetails = InventoryManager.Instance.GetItemDetails(ItemCode);
spriteRenderer.sprite = itemDetails.itemSprite;
if(itemDetails.itemType == ItemType.Reapable_scenery) //如果该物品是风景类型的话
{
gameObject.AddComponent<ItemNudge>();
}
}
}
}
接下来来实现如何做到拾取物品
我们给玩家添加一个新脚本就叫ItemPickUp,因为每一个Item身上都有一个触发器
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemPickUp : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.TryGetComponent<Item>(out Item item))
{
ItemDetails itemDetails = InventoryManager.Instance.GetItemDetails(item.ItemCode);
if (itemDetails.canBePickUp)
{
}
}
}
}
我们还需要一个背包系统InventoryManager,它和SO_ItemList的区别在于,它是一个存储你所能收集到的Item,而SO_ItemList则更像是一个登记所有物品信息的。
我们要写一个新枚举,我们将使用二维数组来控制使用的是哪一个背包。
public enum InventoryLocation
{
player,
chest,
count,
}
public enum ItemType
{
Seed,
Commodity,
Watering_tool,
Hoeing_tool,
Chopping_tool,
Breaking_tool,
Reping_tool,
Collecting_tool,
Reapable_scenery,
Furinture,
None,
Count,
}
接着创建一个结构来管理背包中的Item
[System.Serializable]
public struct InventoryItem
{
public int itemCode;
public int itemQuantity;
}
还需要一个单例模式
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Singleton<T> : MonoBehaviour where T : Component
{
private static T instance;
public static T Instance
{
get
{
return instance;
}
}
protected virtual void Awake()
{
if(instance == null)
{
instance = this as T;
}
else
{
Destroy(gameObject);
}
}
}
w我们需要一个事件处理程序来完成它
using System;
using System.Collections;
using System.Collections.Generic;
public static class EventHandler
{
public static event Action<InventoryLocation,List<InventoryItem>> InventoryUpdateEvent;
public static void CallInventoryUpdateEvent(InventoryLocation inventoryLocation,List<InventoryItem> inventoryLists)
{
if(InventoryUpdateEvent != null)
{
InventoryUpdateEvent(inventoryLocation, inventoryLists);
}
}
}
准备工作就绪,我们就可以继续写InventoryManager了
首先要考虑它的添加和移除物品,以及初始化的时候要创建的数组
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InventoryManager : Singleton<InventoryManager>
{
private Dictionary<int, ItemDetails> itemDetailsDictionary; //通过itemDetails上的itemCode(int类型)的值寻找对应的itemDetails
public List<InventoryItem>[] inventoryLists; //一个存放所有InventoryItem的链表的数组
[HideInInspector] public int[] inventoryListInCapcityInArray; //背包容量大小默认是12
[SerializeField] private SO_ItemList itemLists; //SO_ItemList登记过所有Item
protected override void Awake()
{
base.Awake();
CreateInventoryLists();
CreateItemDetailsDictionary();
}
private void CreateInventoryLists()
{
inventoryLists = new List<InventoryItem>[(int)InventoryLocation.count];//我们有0号背包系统的链表和1号背包系统的链表
for (int i = 0; i < (int)InventoryLocation.count; i++)
{
inventoryLists[i] = new List<InventoryItem>();
}
//出事背包容量列表
inventoryListInCapcityInArray = new int[(int)InventoryLocation.count];
//初始化玩家背包(0号背包)容量
inventoryListInCapcityInArray[(int)InventoryLocation.player] = Settings.playerIntialInventoryCapcity;
}
public void AddItem(InventoryLocation inventoryLocation, Item item,GameObject gameObjectToDelete)
{
AddItem(inventoryLocation, item);
Destroy(gameObjectToDelete);
}
/// <summary>
/// 添加物品
/// </summary>
/// <param name="inventoryLocation"></param>
/// <param name="item"></param>
public void AddItem(InventoryLocation inventoryLocation,Item item)
{
int itemCode = item.ItemCode;
List<InventoryItem> inventoryList = inventoryLists[(int)inventoryLocation];
int itemPositon = FindItemInventory(inventoryLocation, itemCode);
if(itemPositon != -1)
{
AddItemAtPosition(inventoryList, itemCode, itemPositon);//如果找到物品就数量++
}
else
{
AddItemAtPosition(inventoryList, itemCode); //找不到就在空白处新添加物品
}
EventHandler.CallInventoryUpdateEvent(inventoryLocation, inventoryLists[(int)inventoryLocation]);
}
/// <summary>
/// 交换物品顺序
/// </summary>
/// <param name="inventoryLocation"></param>
/// <param name="fromSlotNumber"></param>
/// <param name="toSlotNumber"></param>
public void SwapInventoryItems(InventoryLocation inventoryLocation, int fromSlotNumber, int toSlotNumber)
{
if(fromSlotNumber < inventoryLists[(int)inventoryLocation].Count && toSlotNumber < inventoryLists[(int)inventoryLocation].Count &&
fromSlotNumber != toSlotNumber && toSlotNumber >= 0)
{
InventoryItem fromSlotItem = inventoryLists[(int)inventoryLocation][fromSlotNumber];
InventoryItem toSlotItem = inventoryLists[(int)inventoryLocation][toSlotNumber];
inventoryLists[(int)inventoryLocation][toSlotNumber] = fromSlotItem;
inventoryLists[(int)inventoryLocation][fromSlotNumber] = toSlotItem;
EventHandler.CallInventoryUpdateEvent(inventoryLocation, inventoryLists[(int)inventoryLocation]);
}
}
/// <summary>
/// 将物品添加到背包的位置
/// </summary>
/// <param name="inventoryList"></param>
/// <param name="itemCode"></param>
private void AddItemAtPosition(List<InventoryItem> inventoryList, int itemCode)
{
InventoryItem inventoryItem = new InventoryItem();
inventoryItem.itemCode = itemCode;
inventoryItem.itemQuantity = 1;
inventoryList.Add(inventoryItem);
}
/// <summary>
/// 对于背包中已经有的物品就加数量
/// </summary>
/// <param name="inventoryList"></param>
/// <param name="itemCode"></param>
/// <param name="itemPositon"></param>
private void AddItemAtPosition(List<InventoryItem> inventoryList, int itemCode, int positon)
{
InventoryItem inventoryItem = new InventoryItem();
int quantity = inventoryList[positon].itemQuantity + 1;
inventoryItem.itemCode = itemCode;
inventoryItem.itemQuantity = quantity;
inventoryList[positon] = inventoryItem;
Debug.ClearDeveloperConsole();
}
internal void RemoveItem(InventoryLocation inventoryLocation, int itemCode)
{
List<InventoryItem> inventoryList = inventoryLists[(int)inventoryLocation];
int itemPosition = FindItemInventory(inventoryLocation, itemCode);
if (itemPosition != -1)
{
RemoveItemAtPosition(inventoryList,itemCode,itemPosition);
}
EventHandler.CallInventoryUpdateEvent(inventoryLocation, inventoryLists[(int)inventoryLocation]);
}
private void RemoveItemAtPosition(List<InventoryItem> inventoryList, int itemCode, int position)
{
InventoryItem inventoryItem = new InventoryItem();
int quantity = inventoryList[position].itemQuantity - 1;
if(quantity > 0)
{
inventoryItem.itemQuantity = quantity;
inventoryItem.itemCode = itemCode;
inventoryList[position] = inventoryItem;
}
else
{
inventoryList.RemoveAt(position);
}
}
/// <summary>
/// 判断物品是否在背包里面,找不到就return -1,找到的话就返回发现物品的位置
/// </summary>
/// <param name="inventoryLocation"></param>
/// <param name="itemCode"></param>
/// <returns></returns>
private int FindItemInventory(InventoryLocation inventoryLocation,int itemCode)
{
List<InventoryItem> inventoryList = inventoryLists[(int)inventoryLocation];
for (int i = 0; i < inventoryList.Count; i++)
{
if(inventoryList[i].itemCode == itemCode)
{
return i;
}
}
return -1;
}
/// <summary>
/// 初始化创建的字典
/// </summary>
private void CreateItemDetailsDictionary()
{
itemDetailsDictionary = new Dictionary<int, ItemDetails>();
foreach (var itemDetails in itemLists.itemDetails)
{
itemDetailsDictionary.Add(itemDetails.itemCode,itemDetails);
}
}
/// <summary>
/// 在背包中找ItemDetails
/// </summary>
/// <param name="itemCode"></param>
/// <returns></returns>
public ItemDetails GetItemDetails(int itemCode)
{
ItemDetails itemDetails;
if(itemDetailsDictionary.TryGetValue(itemCode,out itemDetails))
{
return itemDetails;
}
else
{
return null;
}
}
/// <summary>
/// 吃到物品用的调试
/// </summary>
/// <param name="inventoryLists"></param>
private void DebugPrintInventoryList(List<InventoryItem> inventoryLists)
{
foreach (var inventoyItem in inventoryLists)
{
Debug.Log("Item Description:" + InventoryManager.Instance.GetItemDetails(inventoyItem.itemCode).itemDescription +
" Item Quantity:" + inventoyItem.itemQuantity);
}
}
}
回到PickUp脚本,我们就可以直接添加了
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ItemPickUp : MonoBehaviour
{
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.TryGetComponent<Item>(out Item item))
{
ItemDetails itemDetails = InventoryManager.Instance.GetItemDetails(item.ItemCode);
if (itemDetails.canBePickUp)
{
InventoryManager.Instance.AddItem(InventoryLocation.player, item, collision.gameObject);
}
}
}
}
UI:
搞完后就可以制作UI了,直接我们采用熟悉的设计UI模式
一定要注意这个Slot的两个子对象的Raycast Target要取消勾选,不然会导致后面拖拽的时候出现问题。
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class UIInventoryBar : MonoBehaviour
{
[SerializeField] private PlayerController2D playerController2D;
[SerializeField] private Sprite blank16Sprite = null;
[SerializeField] private UIInventorySlot[] inventorySlots = null;
public GameObject inventoryBarDragItem;
private RectTransform rectTransform;
private bool isInventoryBarPositionBottom = true; //判断背包条是否在视角下方
public bool IsInventoryBarPositionBottom
{
get
{
return isInventoryBarPositionBottom;
}
set
{
isInventoryBarPositionBottom = value;
}
}
private void Awake()
{
rectTransform = GetComponent<RectTransform>();
}
private void Update()
{
SwitchInventoryBarPosition();
}
private void OnEnable()
{
EventHandler.InventoryUpdateEvent += InventoryUpdate;
}
private void OnDisable()
{
EventHandler.InventoryUpdateEvent -= InventoryUpdate;
}
private void InventoryUpdate(InventoryLocation inventoryLocation, List<InventoryItem> inventoryList)
{
if(inventoryLocation == InventoryLocation.player)
{
CLearInventorySlots(); //先清空InventroyBar里面所有的InvnetorSlot
if(inventoryList.Count >0 && inventorySlots.Length > 0) //再遍历一遍inventoryList和inventorySlots重新添加回bar里
{
for (int i = 0; i < inventorySlots.Length; i++)
{
if (i < inventoryList.Count)
{
int itemCode = inventoryList[i].itemCode;
ItemDetails itemDetails = InventoryManager.Instance.GetItemDetails(itemCode);
if (itemDetails != null)
{
inventorySlots[i].inventorySlotImage.sprite = itemDetails.itemSprite;
inventorySlots[i].textMeshProUGUI.text = inventoryList[i].itemQuantity.ToString();
inventorySlots[i].itemDetails = itemDetails;
inventorySlots[i].itemQuantity = inventoryList[i].itemQuantity;
}
}
else
{
break;
}
}
}
}
}
private void CLearInventorySlots()
{
if(inventorySlots.Length > 0)
{
for (int i = 0; i < inventorySlots.Length; i++)
{
inventorySlots[i].inventorySlotImage.sprite = blank16Sprite;
inventorySlots[i].textMeshProUGUI.text = "";
inventorySlots[i].itemDetails = null;
inventorySlots[i].itemQuantity = 0;
}
}
}
/// <summary>
/// 切换InventoryBar
/// </summary>
private void SwitchInventoryBarPosition()
{
Vector3 playerViewportPosition = playerController2D.GetPlayerVierportPosition();
if (playerViewportPosition.y > 0.3f && !IsInventoryBarPositionBottom)
{
rectTransform.pivot = new Vector2(0.5f, 0f);
rectTransform.anchorMin = new Vector2(0.5f, 0f);
rectTransform.anchorMax = new Vector2(0.5f, 0f);
rectTransform.anchoredPosition = new Vector2(0f, 2.5f);
isInventoryBarPositionBottom = true;
}
else if(playerViewportPosition.y <= 0.3f && IsInventoryBarPositionBottom)
{
rectTransform.pivot = new Vector2(0.5f, 1f);
rectTransform.anchorMin = new Vector2(0.5f, 1f);
rectTransform.anchorMax = new Vector2(0.5f, 1f);
rectTransform.anchoredPosition = new Vector2(0f, -2.5f);
isInventoryBarPositionBottom = false;
}
}
}
InventorySlot的脚本如下
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using TMPro;
using UnityEngine.UI;
using System;
public class UIInventorySlot : MonoBehaviour,IBeginDragHandler,IDragHandler,IEndDragHandler
{
private Camera mainCamera;
private GameObject draggedItem;
private Transform itemParent;
public Image inventorySlotHighlight;
public Image inventorySlotImage;
public TextMeshProUGUI textMeshProUGUI;
[SerializeField] private UIInventoryBar inventoryBar = null;
[HideInInspector] public ItemDetails itemDetails;
[SerializeField] private GameObject itemPrefab = null;
[HideInInspector] public int itemQuantity;
[SerializeField] private int slotNumber = 0;
private void Start()
{
mainCamera = Camera.main;
itemParent = GameObject.FindGameObjectWithTag(Tags.ItemsParentTransform).transform;
}
public void OnBeginDrag(PointerEventData eventData)
{
if(itemDetails != null)
{
//PlayerController.Instance.DisablePlayerInputAndResetMovement();
draggedItem = Instantiate(inventoryBar.inventoryBarDragItem, inventoryBar.transform);
Image draggedItemImage = draggedItem.GetComponentInChildren<Image>();
draggedItemImage.sprite = inventorySlotImage.sprite;
Debug.Log("draggedItemImage.sprite" + draggedItemImage.sprite);
}
}
public void OnDrag(PointerEventData eventData)
{
if(draggedItem != null)
{
draggedItem.transform.position = Input.mousePosition;
}
}
public void OnEndDrag(PointerEventData eventData)
{
if(draggedItem != null)
{
Destroy(draggedItem);
if(eventData.pointerCurrentRaycast.gameObject != null && eventData.pointerCurrentRaycast.gameObject.GetComponent<UIInventorySlot>() != null)
{
int toSlotNumber = eventData.pointerCurrentRaycast.gameObject.GetComponent<UIInventorySlot>().slotNumber;
InventoryManager.Instance.SwapInventoryItems(InventoryLocation.player,slotNumber,toSlotNumber);
}
else
{
if (itemDetails.canBeDropped)
{
DropSelectedItemMousePosition();
}
}
//PlayerController.Instance.EnablePlayerInput();
}
}
private void DropSelectedItemMousePosition()
{
if(itemDetails != null)
{
Vector3 worldPosition = mainCamera.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, -mainCamera.transform.position.z));
GameObject itemGameobject = Instantiate(itemPrefab, worldPosition, Quaternion.identity, itemParent);
Item item = itemGameobject.GetComponent<Item>();
item.ItemCode = itemDetails.itemCode;
InventoryManager.Instance.RemoveItem(InventoryLocation.player, item.ItemCode);
}
}
}
依次添加
对应的SlotNumer
.....
我们需要创建一个名字叫UIInventoryDraggedItem的预制体,用来处理拖拽出来的图像显示
完成以后我们可以把物品放到场景中试玩一下,可以
我们来做最后的交换位置,在我们之前写的InventoryManager加上这个函数即可
/// <summary>
/// 交换物品顺序
/// </summary>
/// <param name="inventoryLocation"></param>
/// <param name="fromSlotNumber"></param>
/// <param name="toSlotNumber"></param>
public void SwapInventoryItems(InventoryLocation inventoryLocation, int fromSlotNumber, int toSlotNumber)
{
if(fromSlotNumber < inventoryLists[(int)inventoryLocation].Count && toSlotNumber < inventoryLists[(int)inventoryLocation].Count &&
fromSlotNumber != toSlotNumber && toSlotNumber >= 0)
{
InventoryItem fromSlotItem = inventoryLists[(int)inventoryLocation][fromSlotNumber];
InventoryItem toSlotItem = inventoryLists[(int)inventoryLocation][toSlotNumber];
inventoryLists[(int)inventoryLocation][toSlotNumber] = fromSlotItem;
inventoryLists[(int)inventoryLocation][fromSlotNumber] = toSlotItem;
EventHandler.CallInventoryUpdateEvent(inventoryLocation, inventoryLists[(int)inventoryLocation]);
}
}
回到OnEndDrag的函数
public void OnEndDrag(PointerEventData eventData)
{
if(draggedItem != null)
{
Destroy(draggedItem);
if(eventData.pointerCurrentRaycast.gameObject != null && eventData.pointerCurrentRaycast.gameObject.GetComponent<UIInventorySlot>() != null)
{
int toSlotNumber = eventData.pointerCurrentRaycast.gameObject.GetComponent<UIInventorySlot>().slotNumber;
InventoryManager.Instance.SwapInventoryItems(InventoryLocation.player,slotNumber,toSlotNumber);
}
else
{
if (itemDetails.canBeDropped)
{
DropSelectedItemMousePosition();
}
}
//PlayerController.Instance.EnablePlayerInput();
}
}
学习产出:
1
由于时间有限(要去恰午饭了)展示就不展示了,总之我们先做到通过这些来实现玩家有关物体UI的效果,下次更新可能是比赛完以后,我先走啦,拜拜。
版权归原作者 dangoxiba 所有, 如有侵权,请联系我们删除。