演示
功能介绍:
- demo中可以通过按钮向背包中随机添加物品
- 鼠标移动到物品上 能看到物品的信息介绍
- 背包中的物品可以拖拽到其他空格
- 背包的物品可以拖放到仓库,仓库中的物品也可以拖放到背包
- 可以将背包中的装备装备到玩家指定装备槽,类型不同则不能装备
- 相同类型的装备可以将旧装备替换下来
- 背包与仓库中的物品能按照物品的id进行整理
- 将物品拖到格子外,可以出售抓物品
主要脚本
所用到的枚举
/// <summary>
/// 装备类型
/// </summary>
public enum EquipmentType
{
Weapon = 0,//武器
Helmet = 1,//头盔
Corselet = 2,//盔甲
//Ring=3,//戒指
// Barcer=4,//护臂
// Glove=5,//手套
Cloak = 6,//披风
// Legguard=7,//护腿
Trousers = 8,//裤子
Shose = 9,//鞋子
}
/// <summary>
/// 物品的职业
/// </summary>
public enum ItemCareer
{
Universal,//通用
Soldier,//战士
Master,//法师
}
/// <summary>
/// 物品的种类
/// </summary>
public enum ItemType
{
Consumables,//消耗品
Equipment,//装备
Weapon,//武器
}
/// <summary>
/// 物品的质量
/// </summary>
public enum ItemQuality
{
Common,//普通
Advanced,//高级
Legend,//传说
Epic,//史诗
}
工具类
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Tools {
/// <summary>
/// 给button添加事件
/// </summary>
/// <param name="button"></param>
/// <param name="action"></param>
public static void AddButEvent(Button button,UnityEngine.Events.UnityAction action)
{
if (button == null) return;
button.onClick.AddListener(action);
}
/// <summary>
/// 在子物体寻找对应名字的物体上的组件
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="parent"></param>
/// <param name="name"></param>
/// <returns></returns>
public static T FindObjectInChildren<T>(Transform parent,string name) where T: Component
{
T t = null;
T[] ts = parent.GetComponentsInChildren<T>();
foreach (T item in ts)
{
if (item.name == name)
{
t = item;
break;
}
}
return t;
}
}
物品的基类 所有的物品(消耗品,装备,武器,材料等)都需要继承这个类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 物品类(基类)
/// </summary>
public class Item {
public int id;//id
public string name;//name
public ItemType itemType;//装备类型
public ItemQuality itemQuality;//装备质量
public ItemCareer itemCareer;//装备职业
public string description;//装备描述
public int buyPrice;//购买价格
public int sellPrice;//出售价格
public string spritePath;//精灵地址
public int maxNum;//在同一个格子中能存储几个这个类型的物品
public Item(int _id,string _name,ItemType _itemType,ItemQuality _itemQuality,ItemCareer _itemCareer, string _description,int _buyParice,int _sellPrice,string _sprite,int _maxNum)
{
this.id = _id;
this.name = _name;
this.itemType = _itemType;
this.itemQuality = _itemQuality;
this.itemCareer = _itemCareer;
this.description = _description;
this.buyPrice = _buyParice;
this.sellPrice = _sellPrice;
this.spritePath = _sprite;
this.maxNum = _maxNum;
}
}
格子类,可以用来放物品,保存存放在格子中的物品,玩家装备格子(槽)的父类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
/// <summary>
/// 物品槽
/// </summary>
public class Grid : MonoBehaviour,IPointerEnterHandler,IPointerExitHandler,IPointerDownHandler,IPointerUpHandler {
private int itemStoredId;
private int storageSpaceMax;//物品槽能放相同物品的最大数量
private int currentStorageNum;//当前物品槽中的物品数量
public bool isEmpty=true;//物品槽是否为空
private List<Item> itemList;//存放的物品
public int StorageSpaceMax
{
get
{
return storageSpaceMax;
}
}
public int CurrentStorageNum
{
get
{
return currentStorageNum;
}
}
public bool IsEmpty
{
get
{
return isEmpty;
}
}
public List<Item> ItemList
{
get
{
return itemList;
}
}
public int ItemStoredId
{
get
{
return itemStoredId;
}
}
/// <summary>
/// 向格子里添加物品
/// </summary>
/// <param name="_item"></param>
public void AddItem(Item _item)
{
if (itemList == null)
{
itemList = new List<Item>();
}
if (isEmpty)
{
Debug.Log("aaaaa");
isEmpty = false;
storageSpaceMax = _item.maxNum;
GameObject itemUIGO = Instantiate(Resources.Load<GameObject>("ItemUI"));
itemUIGO.transform.SetParent(transform, false);
itemUIGO.transform.localScale = Vector3.one;
ItemUI itemUI = itemUIGO.GetComponent<ItemUI>();
itemUI.SetItemShow(_item,1);
itemList.Add(_item);
itemStoredId = _item.id;
currentStorageNum++;
}else
if (currentStorageNum<storageSpaceMax)
{
ItemUI itemUI = transform.GetComponentInChildren<ItemUI>();
itemUI.SetTextADD();
itemList.Add(_item);
currentStorageNum++;
}
else
{
Debug.Log("格子类存储数量到达上限");
}
}
/// <summary>
/// 移除格子里的物品
/// </summary>
/// <param name="_item"></param>
/// <returns></returns>
public Item RemoveItem(Item _item)
{
if (itemList == null||itemList.Count==0)
{
Debug.Log("要移除的物品不存在");
return null;
}
if (itemList.Contains(_item))
{
currentStorageNum--;
itemList.Remove(_item);
transform.GetComponentInChildren<ItemUI>().SetTextReduce();
if (currentStorageNum==0)
{
isEmpty = true;
itemStoredId = -1;
storageSpaceMax = 0;
transform.GetComponentInChildren<ItemUI>().DestorySelf() ;
}
return _item;
}
else
{
Debug.Log("要移除的物品不存在");
return null;
}
}
public void OnPointerDown(PointerEventData eventData)
{
if (gameObject.name.Contains("EquipmentGrid")) return;
if (!IsEmpty)
{
InventoryManger.Instance.BePickGrid = this;
InventoryManger.Instance.showItemUI.SetItemShow(itemList[0]);
InventoryManger.Instance.IsPickedItem = true;
RemoveItem(itemList[0]);
}
}
public void OnPointerUp(PointerEventData eventData)
{
// throw new System.NotImplementedException();
}
public void OnPointerEnter(PointerEventData eventData)
{
if (!IsEmpty)
{
InventoryManger.Instance.showInfo.Show();
InventoryManger.Instance.showInfo.SetShowInfo(itemList[0]);
InventoryManger.Instance.IsShowItmInfo = true;
}
}
public void OnPointerExit(PointerEventData eventData)
{
if (!IsEmpty)
{
InventoryManger.Instance.showInfo.Hide();
}
InventoryManger.Instance.IsShowItmInfo = false;
}
}
背包类的基类 背包与仓库都会继承这个类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 背包类型的父类
/// </summary>
public class Inventory : MonoBehaviour {
public List<Grid> gridsList;//能存储物品的的格子列表
void Start()
{
if (gridsList == null)
gridsList = new List<Grid>();
gridsList.AddRange( GetComponentsInChildren<Grid>());
}
/// <summary>
/// 向物品槽添加物品
/// </summary>
/// <param name="itemId"></param>
public bool AddItemToGrid(int itemId)
{
Grid grid;
if (FindSameIdGrid(itemId, out grid))
{
Item item = InventoryManger.Instance.GetItemObject(itemId);
grid.AddItem(item);
return true;
}else if (FindEmptyGrid(out grid))
{
Item item = InventoryManger.Instance.GetItemObject(itemId);
grid.AddItem(item);
return true;
}
else
{
Debug.Log("无格子可放");
}
return false;
}
/// <summary>
/// 向物品槽添加物品
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public bool AddItemToGrid(Item item)
{
Grid grid;
if (FindSameIdGrid(item.id, out grid))
{
grid.AddItem(item);
return true;
}
else if (FindEmptyGrid(out grid))
{
grid.AddItem(item);
return true;
}
else
{
Debug.Log("无格子可放");
}
return false;
}
/// <summary>
/// 整理 按照id的顺序刷新列表
/// </summary>
public void RefreshKnapsack()
{
//将格子物品按id排序存储
if (gridsList.Count == 0) return;
List<Grid> grids = new List<Grid>();
for (int i = 0; i < gridsList.Count; i++)
{
if (gridsList[i].isEmpty) continue;
if (grids.Count==0)
{
grids.Add(gridsList[i]);
continue;
}
for (int j = 0; j < grids.Count; j++)
{
if (gridsList[i].ItemStoredId < grids[0].ItemStoredId)
{
grids.Insert(0, gridsList[i]);
break;
}
else if (gridsList[i].ItemStoredId >= grids[grids.Count - 1].ItemStoredId)
{
grids.Add(gridsList[i]);
break;
}
else if (j < grids.Count - 1 && gridsList[i].ItemStoredId >= grids[j].ItemStoredId && gridsList[i].ItemStoredId < grids[j + 1].ItemStoredId)
{
grids.Insert(j + 1, gridsList[i]);
break;
}
}
}
//将格式按照存放的物品id调换位置
for (int i = 0; i < grids.Count; i++)
{
Debug.Log(grids[i].ItemStoredId+" nums:"+grids[i].CurrentStorageNum+" " + grids[i].isEmpty);
grids[i].transform.SetSiblingIndex(i);
}
grids.Clear();
//防止由于界面的格子顺序与列表中不一致而在添加时显示不是从前往后的顺序添加
gridsList.Clear();
gridsList.AddRange(GetComponentsInChildren<Grid>());
}
/// <summary>
/// 找出一个已经存有相同物品的格子 且格子的存储数没达到上限
/// </summary>
/// </summary>
/// <param name="id"></param>
/// <param name="grid"></param>
/// <returns></returns>
private bool FindSameIdGrid(int id,out Grid grid)
{
for (int i = 0; i < gridsList.Count; i++)
{
if (gridsList[i].IsEmpty == false && gridsList[i].CurrentStorageNum < gridsList[i].StorageSpaceMax && id == gridsList[i].ItemList[0].id)
{
grid= gridsList[i];
return true;
}
}
grid = null;
return false;
}
/// <summary>
/// 找出一个空格子
/// </summary>
/// <param name="grid">out出找到的格子</param>
/// <returns>是否找到</returns>
private bool FindEmptyGrid(out Grid grid)
{
for (int i = 0; i < gridsList.Count; i++)
{
if (gridsList[i].IsEmpty)
{
grid = gridsList[i];
return true;
}
}
grid = null;
return false;
}
}
界面UI的类 可以根据装备的类型 获取sprite的路径 然后显示在界面
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class ItemUI : MonoBehaviour
{
private Image itemImage;
public Text itemNum;
public int currenNum=0;
private Vector3 off;
public Item currentItem;
public int CurrenNum
{
get
{
return currenNum;
}
}
void Start()
{
}
void Update()
{
}
public void SetItemShow(Item item,int num=1)
{
if (itemImage==null)
{
itemImage = GetComponent<Image>();
}
itemImage.sprite= Resources.Load<Sprite>(item.spritePath);
currentItem = item;
if (itemNum == null)
{
itemNum = Tools.FindObjectInChildren<Text>(transform, "numText");
}
currenNum = num;
if (num == 1 || num == 0)
{
itemNum.text = "";
}
else
{
itemNum.text = num.ToString(); ;
}
}
public void SetTextADD()
{
if (itemNum==null)
{
itemNum = Tools.FindObjectInChildren<Text>(transform, "numText");
}
currenNum +=1;
if (currenNum == 1|| currenNum == 0)
{
itemNum.text = "";
}
else
{
itemNum.text = currenNum.ToString(); ;
}
}
public void SetTextReduce()
{
if (itemNum == null)
{
itemNum = Tools.FindObjectInChildren<Text>(transform, "numText");
}
currenNum -= 1;
if (currenNum == 1 || currenNum == 0)
{
itemNum.text = "";
}
else
{
itemNum.text = currenNum.ToString(); ;
}
}
public void DestorySelf()
{
Destroy(gameObject);
}
public void Show()
{
gameObject.SetActive(true);
}
public void Hide()
{
gameObject.SetActive(false);
}
}
管理类,主要负责物品json信息的读取 处理玩家出售,移动物品的逻辑
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using LitJson;
using UnityEngine.UI;
using UnityEngine.EventSystems;
public class InventoryManger : MonoBehaviour {
private static InventoryManger instance;
public ItemMessageInfo showInfo;
public ItemUI showItemUI;
public Dictionary<int, JsonData> jsonDatasDic = new Dictionary<int, JsonData>();//存储读取到的物品信息 按id存储
private bool isPickedItem = false;
private bool isShowItmInfo = false;
private Grid bePickGrid;
public static InventoryManger Instance
{
get
{
if (instance==null)
{
instance = GameObject.FindObjectOfType(typeof(InventoryManger)) as InventoryManger;
}
return instance;
}
}
public bool IsPickedItem
{
get
{
return isPickedItem;
}
set
{
isPickedItem = value;
}
}
public bool IsShowItmInfo
{
get
{
return isShowItmInfo;
}
set
{
isShowItmInfo = value;
}
}
public Grid BePickGrid
{
get
{
return bePickGrid;
}
set
{
bePickGrid = value;
}
}
void Awake()
{
instance = this;
InitJsonMessage();
}
void Start()
{
Debug.Log("aaa");
}
void Update()
{
#if UNITY_EDITOR
if (Input.GetMouseButtonDown(0))
{
GetOverUI(GameObject.Find("Canvas"));
}
#endif
if (IsPickedItem)
{
if (Input.GetMouseButton(0))
{
showItemUI.Show();
showInfo.Hide();
showItemUI.transform.position = Input.mousePosition;
}
if (Input.GetMouseButtonUp(0))
{
List<GameObject> objects = GetOverUI(GameObject.Find("Canvas"));
for (int i = 0; i < objects.Count; i++)
{
if (objects[i].name.Contains("Grid"))
{
//1,是玩家的装备格子
if (objects[i].name.Contains("EquipmentGrid"))
{
EquipmentGrid equipmentGrid = objects[i].GetComponent<EquipmentGrid>();
if (showItemUI.currentItem.itemType == ItemType.Weapon && equipmentGrid.equipmentType == EquipmentType.Weapon)
{
if (equipmentGrid.CurrentItem == null)
{
equipmentGrid.AddItem(showItemUI.currentItem);
equipmentGrid.CurrentItem = showItemUI.currentItem;
}
else//替换掉 替换掉,原来的装备放回背包
{
Knapsack.Instance.AddItemToGrid(equipmentGrid.CurrentItem);
equipmentGrid.RemoveItem(equipmentGrid.CurrentItem);
equipmentGrid.AddItem(showItemUI.currentItem);
equipmentGrid.CurrentItem = showItemUI.currentItem;
}
}
else if (showItemUI.currentItem.itemType == ItemType.Equipment && equipmentGrid.equipmentType == (showItemUI.currentItem as Equipment).equipmentType)
{
if (equipmentGrid.CurrentItem==null)
{
equipmentGrid.AddItem(showItemUI.currentItem);
equipmentGrid.CurrentItem = showItemUI.currentItem;
}
else //替换掉,原来的装备放回背包
{
Knapsack.Instance.AddItemToGrid(equipmentGrid.CurrentItem);
equipmentGrid.RemoveItem(equipmentGrid.CurrentItem);
equipmentGrid.AddItem(showItemUI.currentItem);
equipmentGrid.CurrentItem = showItemUI.currentItem;
}
}
else //放回原处
{
bePickGrid.AddItem(showItemUI.currentItem);
}
}
else
{
//2,不是玩家装备格子
Grid grid = objects[i].GetComponent<Grid>();
if (grid.IsEmpty)//格子为空时
{
grid.AddItem(showItemUI.currentItem);
}
else if (showItemUI.currentItem.id == grid.ItemStoredId && grid.CurrentStorageNum < grid.StorageSpaceMax)//格子中有物品但未达到该类物品的存储上限
{
grid.AddItem(showItemUI.currentItem);
}
else//格子中有物品且达到该类物品的存储上限
{
//回到背包TODO
bePickGrid.AddItem(showItemUI.currentItem);
}
}
break;
}
else
{
//出售掉装备 跟新玩家的金币数量
//TODO
}
}
IsPickedItem = false;
}
}
else
{
showItemUI.Hide();
BePickGrid = null;
}
if (IsPickedItem==false&&IsShowItmInfo)
{
showInfo.SetPosition(Input.mousePosition);
}
else
{
showInfo.Hide();
}
}
/// <summary>
/// 解析json 存储数据
/// </summary>
public void InitJsonMessage()
{
TextAsset textAsset = Resources.Load<TextAsset>("ItemJosn");
if (textAsset==null)
{
Debug.Log("null");
return;
}
string jsonString = textAsset.text;
Debug.Log(jsonString);
JsonData data = JsonMapper.ToObject(jsonString);
JsonData data1 = data["ItemJsonList"];
for (int i = 0; i < data1.Count; i++)
{
jsonDatasDic.Add(i+1, data1[i]);
}
}
/// <summary>
/// 获取对应id物品的精灵图片路径
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public string GetSpritePath(int id)
{
if (!jsonDatasDic.ContainsKey(id)) return null;
JsonData data = jsonDatasDic[id];
return data["spritePath"].ToString();
}
/// <summary>
/// 获取相同装备在同一个物品槽的存放数量
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public int GetSameNum(int id)
{
if (!jsonDatasDic.ContainsKey(id)) return 1;
JsonData data = jsonDatasDic[id];
return int.Parse( data["maxNum"].ToString());
}
/// <summary>
/// 根据id 和json的数据实例化item
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public Item GetItemObject(int id)
{
Item item = null;
if (jsonDatasDic.Count==0)
{
InitJsonMessage();
}
if (!jsonDatasDic.ContainsKey(id)) return null;
JsonData data = jsonDatasDic[id];
string name = data["name"].ToString();
ItemType itemType = (ItemType)System.Enum.Parse(typeof(ItemType), data["itemType"].ToString());
ItemQuality itemQuality = (ItemQuality)System.Enum.Parse(typeof(ItemQuality), data["itemQuality"].ToString());
ItemCareer itemCareer = (ItemCareer)System.Enum.Parse(typeof(ItemCareer), data["itemCareer"].ToString());
string description = data["description"].ToString();
int buyPrice = int.Parse(data["buyPrice"].ToString());
int sellPrice = int.Parse(data["sellPrice"].ToString());
string spritePath = data["spritePath"].ToString();
int maxNum = int.Parse(data["maxNum"].ToString());
switch (itemType)
{
case ItemType.Consumables:
int hp = int.Parse(data["hp"].ToString());
int mp = int.Parse(data["mp"].ToString());
item = new Consumables(id,name,itemType,itemQuality,itemCareer,description,buyPrice,sellPrice,spritePath,maxNum,hp,mp);
break;
case ItemType.Equipment:
int defensivePower = int.Parse(data["defensivePower"].ToString());
int agility = int.Parse(data["agility"].ToString());
int stamina = int.Parse(data["stamina"].ToString());
EquipmentType equipmentType = (EquipmentType)System.Enum.Parse(typeof(EquipmentType), data["equipmentType"].ToString());
item = new Equipment(id, name, itemType, itemQuality, itemCareer, description, buyPrice, sellPrice, spritePath, maxNum, defensivePower, agility, stamina, equipmentType);
break;
case ItemType.Weapon:
int damage = int.Parse(data["damage"].ToString());
item = new Weapon(id, name, itemType, itemQuality, itemCareer, description, buyPrice, sellPrice, spritePath, maxNum, damage);
break;
default:
break;
}
return item;
}
/// <summary>
/// 整理背包
/// </summary>
public void ClearUpKnapsack()
{
Knapsack.Instance.RefreshKnapsack();
}
/// <summary>
/// 整理仓库
/// </summary>
public void ClearUpWareHouse()
{
Warehouse.Instance.RefreshKnapsack();
}
/// <summary>
/// 获取鼠标停留处UI
/// </summary>
/// <param name="canvas"></param>
/// <returns></returns>
public List<GameObject> GetOverUI(GameObject canvas)
{
List<GameObject> list = new List<GameObject>();
PointerEventData pointerEventData = new PointerEventData(EventSystem.current);
pointerEventData.position = Input.mousePosition;
GraphicRaycaster gr = canvas.GetComponent<GraphicRaycaster>();
List<RaycastResult> results = new List<RaycastResult>();
gr.Raycast(pointerEventData, results);
foreach (var item in results)
{
list.Add(item.gameObject);
}
return list;
}
public void Test()//only to test
{
int a = Random.Range(1, 10);
Debug.Log("randon:" + a);
if (Knapsack.Instance.AddItemToGrid(a))
{
Debug.Log("添加成功");
}
}
public void Test2()
{
}
}
物品信息json文件的格式
{
"ItemJsonList": [
{
"id": 1,
"name": "蓝瓶",
"itemType": "Consumables",
"itemQuality": "Advanced",
"itemCareer": "Universal",
"description": "加蓝",
"buyPrice": "10",
"sellPrice": "5",
"spritePath": "Sprite/Items/mp",
"maxNum": 10,
"hp": 0,
"mp": 50
},
{
"id": 2,
"name": "红瓶",
"itemType": "Consumables",
"itemQuality": "Advanced",
"itemCareer": "Universal",
"description": "加血",
"buyPrice": "10",
"sellPrice": "5",
"spritePath": "Sprite/Items/hp",
"maxNum": 10,
"hp": 50,
"mp": 0
},
{
"id": 3,
"name": "头盔",
"itemType": "Equipment",
"itemQuality": "Advanced",
"itemCareer": "Universal",
"description": "增加防御",
"buyPrice": "10",
"sellPrice": "5",
"spritePath": "Sprite/Items/helmets",
"maxNum": 1,
"defensivePower": 20,
"agility": 5,
"stamina": 20,
"equipmentType": "Helmet"
},
{
"id": 4,
"name": "盔甲",
"itemType": "Equipment",
"itemQuality": "Advanced",
"itemCareer": "Universal",
"description": "增加防御",
"buyPrice": "10",
"sellPrice": "5",
"spritePath": "Sprite/Items/armor",
"maxNum": 1,
"defensivePower": 50,
"agility": 5,
"stamina": 20,
"equipmentType": "Corselet"
}
}
]
}
完整项目:https://github.com/Tend-R/Repository_new unity2017.3