思路
1、创建UI面板以承载仓库中的物品和已装备的物品,以及物品名称和物品描述;
2、创建ItemData.cs装载物品的缩略图、描述并创建ItemData对象
3、创建一个脚本,声明并定义承载ItemData对象的数组、承载缩略图的数组。
4、显示缩略图、文本
5、实现物品交换
6、创建鼠标进、出和点击事件,分别用来显示相应物体名称、描述、缩略图和物品交换
实例
一、创建UI面板
含有物品栏、已装备物品、物品名和物品信息文本
二、创建ItemData对象
1、创建ItemData.cs,声明ItemData对象的属性
[CreateAssetMenu(menuName ="Items/Item")]
public class ItemData : ScriptableObject
{
public string description;
public Sprite thumbnail;
public GameObject gameModle;
}
2、创建ItemData.cs的子类EquipmentData.cs,增加类型属性
[CreateAssetMenu(menuName = "Items/Equipment")]
public class EquipmentData : ItemData
{
public enum ToolType
{
Hoe, WateringCan, Axe, Pickaxe
}
public ToolType toolType;
}
二者可以合并为:
[CreateAssetMenu(menuName ="Items/Item")]
public class ItemData : ScriptableObject
{
public string description;
public Sprite thumbnail;
public GameObject gameModel;
public enum ToolType
{
Hoe, WateringCan, Axe, Pickaxe
}
public ToolType toolType;
}
3、在Unity中,创建各ItemData对象,分配各ItemData对象的物品信息(缩略图、描述、类型等)
三、分配ItemData对象
1、创建Manager空物体,添加InventoryManager.cs组件,设置单例
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static InventorySlot;
public class InventoryManager : MonoBehaviour
{
public static InventoryManager Instance { get; private set; }
private void Awake()
{
if (Instance != null && Instance != this){ Destroy(this); }
else { Instance = this; }
}
}
2、编辑InventoryManager.cs,创建ItemData对象数组(物品栏中的物品)和ItemData对象
//ItemData对象数组(物品栏中的物品)
public ItemData[] tools = new ItemData[8];
//装备槽中已装备的物品
public ItemData equippedTool = null;
3、在Unity中为tools数组(物品栏中的物品)分配ItemData对象
4、目的:可以通过引用InventoryManager类,直接调用ItemData类的物品的物品信息
四、显示UI物品缩略图
1、直接显示手持物品槽中物品的缩略图(本实例中UI未设置)
(1) 给Manage添加UIManager.cs组件,设置单例
public static UIManager Instance { get; private set; }
private void Awake()
{
if (Instance != null && Instance != this) { Destroy(this);}
else{ Instance = this; }
}
(2) 编辑UIManager.cs,添加显示缩略图的方法,并在Start方法中调用这个方法
//手持物品的物品槽中的子物体的图片(缩略图)
public Image toolEquipSlotImage;
private void Start()
{
RenderInventory();
}
public void RenderInventory()
{
//临时变量equippedTool(手持物品)
ItemData equippedTool = InventoryManager.Instance.equippedTool;
if(equippedTool != null)
{
toolEquipSlotImage.sprite = equippedTool.thumbnail;
toolEquipSlotImage.gameObject.SetActive(true);
return;
}
toolEquipSlotImage.gameObject.SetActive(false);
}
2、显示已装备物品的缩略图(后续更改为添加InventorySlot.cs子类HandInventorySlot.cs组件)
(1) 给已装备物品槽(见UI面板图)添加InventorySlot.cs组件,创建一个单独的显示缩略图的方法
//待显示的ItemData对象
ItemData itemToDisplay;
//待显示物品的的子物体
public Image itemDisplayImage;
public void Display(ItemData itemToDisplay)
{
if (itemToDisplay != null && itemToDisplay.thumbnail != null)
{
itemDisplayImage.sprite = itemToDisplay.thumbnail;
this.itemToDisplay = itemToDisplay;
itemDisplayImage.gameObject.SetActive(true);
return;
}
itemDisplayImage.gameObject.SetActive(false);
this.itemToDisplay = null;
}
(2) 新建HandInventorySlot.cs
public class HandInventorySlot : InventorySlot
(3) 编辑UIManager.cs,添加显示缩略图的方法
//已装备物品(物品栏旁边的装备栏)
public HandInventorySlot toolHandSlot;
public void RenderInventory()
{
//显示已装备物品缩略图
toolHandSlot.Display(InventoryManager.Instance.equippedTool);
}
3、显示物品栏中的物品的缩略图
(1) 编辑预制体InventorySlot,添加InventorySlot.cs组件(每个物品栏中的物品都能显示自己的缩略图)
(2) 编辑UIManager.cs,创建预制体InventorySlot数组(组成物品栏中的物品)
public InventorySlot[] toolSlots;
(3) 在UIManager.cs中创建RenderInventoryPanel方法,显示物品栏中物品对应的缩略图
void RenderInventoryPanel(ItemData[] slots, InventorySlot[] uiSlots)
{
for (int i = 0; i < uiSlots.Length; i++)
{
uiSlots[i].Display(slots[i]);
}
}
(4) 编辑UIManager.cs中的RenderInventory方法,调用RenderInventoryPanel方法(注意参数)
public void RenderInventory()
{
ItemData[] inventoryToolSlot = InventoryManager.Instance.tools;
RenderInventoryPanel(inventoryToolSlot, toolSlots);
}
五、显示文本
1、编辑UIManager.cs,添加显示文本的方法
public Text itemNameText;
public Text itemDescriptionText;
public void DisplayItemInfo(ItemData data)
{
if(data == null)
{
itemNameText.text = "";
itemDescriptionText.text = "";
return;
}
itemNameText.text = data.name;
itemDescriptionText.text = data.description;
}
2、编辑InventorySlot.cs,设置鼠标悬停,调用DisplayItemInfo方法显示文本
public class InventorySlot : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
ItemData itemToDisplay;
public void OnPointerEnter(PointerEventData eventData)
{
UIManager.Instance.DisplayItemInfo(itemToDisplay);
}
public void OnPointerExit(PointerEventData eventData)
{
UIManager.Instance.DisplayItemInfo(null);
}
}
六、实现物品交换
1、编辑InventorySlot.cs,为物品栏中的物品分配索引值
//物品栏中被点击的物品的索引
int slotIndex;
//分配索引
public void AssignIndex(int slotIndex)
{
this.slotIndex = slotIndex;
}
2、编辑UIManager.cs,为物品栏中各物品分配索引值,并在Start方法中调用分配索引值的方法
public InventorySlot[] toolSlots;
private void Start()
{
AssignSlotIndex();
}
public void AssignSlotIndex()
{
for (int i = 0; i < toolSlots.Length; i++)
{
toolSlots[i].AssignIndex(i);
}
}
3、编辑InventoryManager.cs,创建物品由物品栏到装备栏的方法
public void InventoryToHand(int slotIndex)
{
//取出物品栏中的物品(在位置A)缓存到toolToEquip这个临时变量(临时位置)中
ItemData toolToEquip = tools[slotIndex];
//把已装备的物品转移到移出的物品的位置(位置A)上
tools[slotIndex] = equippedTool;
//把临时变量中的物品从临时位置转移到装备物品的位置上
equippedTool = toolToEquip;
//更新物品缩略图
UIManager.Instance.RenderInventory();
}
4、编辑InventorySlot.cs,增加点击事件
public class InventorySlot : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler,IPointerClickHandler
{
public virtual void OnPointerClick(PointerEventData eventData)
{
InventoryManager.Instance.InventoryToHand(slotIndex);
}
}
5、编辑InventoryManager.cs,创建物品由装备栏到物品栏的方法
public void HandToInventory()
{
for(int i = 0;i < tools.Length; i++)
{
if(tools[i] == null)
{
tools[i] = equippedTool;
equippedTool = null;
break;
}
}
UIManager.Instance.RenderInventory();
}
6、编辑HandInventorySlot.cs,设置点击已装备物品时,调用覆盖步骤4的点击事件的方法
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using static InventorySlot;
public class HandInventorySlot : InventorySlot
{
public override void OnPointerClick(PointerEventData eventData)
{
InventoryManager.Instance.HandToInventory();
}
}
编辑UIManager.cs,设置显示已装备物品
public void RenderInventory()
{
ItemData[] inventoryToolSlot = InventoryManager.Instance.tools;
RenderInventoryPanel(inventoryToolSlot, toolSlots);
// 显示已装备物品缩略图
toolHandSlot.Display(InventoryManager.Instance.equippedTool);
}