背包管理器
/****************************************************
* 文件名称:BagManager.cs
* 作 者:Blink
* 邮 箱:1614283998@qq.com
* 创建日期:2019/11/11 16:51:05
* 功 能:背包管理器
****************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class BagManager
{
#region 单例
private static BagManager mInstance = null;
public static BagManager Instance
{
get
{
if (mInstance == null)
mInstance = new BagManager();
return mInstance;
}
}
private BagManager() { }
#endregion
// 刷新UI的回调
public Action<BagGrid, bool> OnRefreshGridUI = null;
// 背包已满回调
public Action OnFilled = null;
private Func<int, BaseItem> OnGetItem = null;
// 背包格子对象数组
private BagGrid[] mBagGrids = null;
public BagGrid[] BagGrids
{
get
{
return mBagGrids;
}
}
/// <summary>
/// 初始化
/// </summary>
/// <param name="bagGridCount">背包格子数量</param>
/// <param name="datas">背包数据</param>
public virtual void Init(int bagGridCount, Func<int, BaseItem> getItemHandle, List<BagData> datas = null)
{
OnGetItem = getItemHandle;
// 初始化背包格子数组
mBagGrids = new BagGrid[bagGridCount];
for (int i = 0; i < mBagGrids.Length; i++)
{
mBagGrids[i] = new BagGrid(i);
}
// 初始化背包物品数据
if (datas != null)
{
foreach (BagData data in datas)
{
if (data == null) continue;
BaseItem item = GetItemById(data.ID);
if (item != null)
{
mBagGrids[data.Index].SetItem(GetItemById(data.ID), data.Amount);
}
}
}
}
/// <summary>
/// 通过物品ID添加物品到背包
/// </summary>
/// <param name="id">物品ID</param>
/// <param name="amount">数量</param>
public virtual void AddItem(int id, int amount = 1)
{
BaseItem item = GetItemById(id);
AddItem(item, amount);
}
/// <summary>
/// 通过物品对象添加物品
/// </summary>
/// <param name="item">需要添加的物品对象</param>
/// <param name="amount">数量</param>
public virtual void AddItem(BaseItem item, int amount = 1)
{
if (item == null)
{
throw new System.Exception("Bag AddItem Exception:需要添加到背包的Item为null!");
}
else
{
BagGrid grid = null;
while (amount > 0)
{
grid = FindUsableGrid(item.ID);
if (grid != null)
{
int remainCapacity = grid.IsEmpty ? item.Capacity : (grid.Item.Capacity - grid.Amount);
int tmp = amount;
if (tmp > remainCapacity)
tmp = remainCapacity;
if (grid.IsEmpty)
{
grid.SetItem(item, tmp);
//TODO 刷新UI显示,新的物品
OnRefreshGridUI(grid, true);
}
else
{
grid.AddAmount(tmp);
//TODO 刷新UI显示,刷新数量
OnRefreshGridUI(grid, false);
}
// 剩余没存的物品个数,如果<=0则已经存储完
amount -= remainCapacity;
}
else
{
//TODO 背包已满
break;
}
}
}
}
/// <summary>
/// 根据格子索引减少物品数量
/// </summary>
/// <param name="index">格子索引</param>
/// <param name="amount">物品数量</param>
public virtual void SubItemByIndex(int index, int amount = 1)
{
BagGrid grid = FindGridByIndex(index);
if (grid == null) return;
grid.SubAmount(amount);
OnRefreshGridUI(grid, false);
}
/// <summary>
/// 通过物品ID减少物品数量
/// </summary>
/// <param name="id">物品ID</param>
/// <param name="amount">amount</param>
public virtual void SubItemById(int id, int amount = 1)
{
while (amount > 0)
{
BagGrid grid = FindGridById(id);
if (grid == null) break;
// 如果格子中的物品数量大于需要减少的数量
if (grid.Amount >= amount)
{
grid.SubAmount(amount);
amount = 0;
}
else
{
amount -= grid.Amount;
grid.SubAmount(grid.Amount);
}
////TODO 刷新UI
//if (grid.IsEmpty)
//{
// // 清空格子UI显示
// OnRefreshGridUI(grid, false);
//}
//else
//{
// // 刷新数量显示
// OnRefreshGridUI(grid, false);
//}
OnRefreshGridUI(grid, false);
}
}
/// <summary>
/// 判断物品数量是否充足
/// </summary>
/// <param name="id">物品ID</param>
/// <param name="amount">需进行比较的物品个数</param>
/// <returns></returns>
public bool IsEnough(int id, int amount)
{
return GetItemCount(id) >= amount;
}
/// <summary>
/// 获取背包中对应ID物品的总个数
/// </summary>
/// <param name="id">物品ID</param>
/// <returns></returns>
public int GetItemCount(int id)
{
int count = 0;
if (mBagGrids != null)
{
for (int i = 0; i < mBagGrids.Length; i++)
{
if (mBagGrids[i] == null || mBagGrids[i].IsEmpty) continue;
if (mBagGrids[i].Item.ID == id)
count += mBagGrids[i].Amount;
}
}
return count;
}
/// <summary>
/// 获取背包中物品存储数据列表(存档用)
/// </summary>
/// <returns></returns>
public List<BagData> GetBagDatas()
{
if (mBagGrids == null) return null;
List<BagData> list = new List<BagData>();
for (int i = 0; i < mBagGrids.Length; i++)
{
if (mBagGrids[i] == null || mBagGrids[i].IsEmpty) continue;
list.Add(new BagData
{
ID = mBagGrids[i].Item.ID,
Index = mBagGrids[i].Index,
Amount = mBagGrids[i].Amount
});
}
return list;
}
/// <summary>
/// 通过物品ID获取物品
/// </summary>
/// <param name="id">物品ID</param>
/// <returns></returns>
public BaseItem GetItemById(int id)
{
if (OnGetItem != null)
{
return OnGetItem(id);
}
return null;
}
/// <summary>
/// 根据格子索引查找格子
/// </summary>
/// <param name="index">格子索引</param>
/// <returns>查找到的格子</returns>
public BagGrid FindGridByIndex(int index)
{
if (mBagGrids == null || index < 0 || index >= mBagGrids.Length)
return null;
return mBagGrids[index];
}
/// <summary>
/// 根据物品ID查找格子(返回第一个查找到的格子)
/// </summary>
/// <param name="id">物品ID</param>
/// <returns>查找到格子</returns>
public BagGrid FindGridById(int id)
{
if (mBagGrids == null) return null;
for (int i = 0; i < mBagGrids.Length; i++)
{
if (mBagGrids[i] == null || mBagGrids[i].IsEmpty) continue;
if (mBagGrids[i].Item.ID == id)
return mBagGrids[i];
}
return null;
}
/// <summary>
/// 查找可用的格子,返回格子索引,没有找到返回-1
/// </summary>
/// <param name="id">物品ID</param>
/// <returns>查找到的格子</returns>
protected virtual BagGrid FindUsableGrid(int id)
{
BagGrid grid = null;
for (int i = 0; i < mBagGrids.Length; i++)
{
if (mBagGrids[i] == null)
{
continue;
}
// 空格子
else if (mBagGrids[i].IsEmpty)
{
if (grid == null)
{
grid = mBagGrids[i];
}
}
// 未放满
else if (mBagGrids[i].Item.ID == id && mBagGrids[i].Amount < mBagGrids[i].Item.Capacity)
{
grid = mBagGrids[i];
break;
}
}
return grid;
}
#region 测试
public override string ToString()
{
string info = "";
foreach (var g in mBagGrids)
{
if (!g.IsEmpty)
{
info += (g.ToString() + "\n");
}
}
return info;
}
//END
#endregion
}
测试
-
创建背包UI界面
![《Unity:实现背包系统(二)》](https://i.loli.net/2019/11/13/ftoHv21bwuVcl64.png)
-
创建背包格子UI脚本
脚本实现了IPointerDownHandler接口,使格子可以对点击事件进行相应操作
/****************************************************
* 文件名称:UIGrid.cs
* 作 者:Blink
* 邮 箱:1614283998@qq.com
* 创建日期:2019/11/11 18:35:10
* 功 能:Noting
****************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class UIGrid : MonoBehaviour,IPointerDownHandler
{
public int index;
public BagPanel panel;
public Text txtAmount;
public Image imgIcon;
// 初始化,传入格子索引和背包面板对象
public void Init(int index,BagPanel panel)
{
this.index = index;
this.panel = panel;
txtAmount = transform.Find("txtAmount").GetComponent<Text>();
imgIcon = transform.Find("Sprite").GetComponent<Image>();
Clear();
}
public void OnPointerDown(PointerEventData eventData)
{
// 鼠标左键按下,显示物品信息
if(eventData.button == PointerEventData.InputButton.Left)
{
panel.ShowInfo(index);
}
// 不是鼠标右键按下就减少数量
else
{
BagManager.Instance.SubItemByIndex(index);
}
}
// 清空格子显示
public void Clear()
{
imgIcon.gameObject.SetActive(false);
imgIcon.sprite = null;
txtAmount.text = "";
txtAmount.gameObject.SetActive(false);
}
// 刷新显示
public void RefreshUI(Sprite sprite,int amount)
{
if(imgIcon.gameObject.activeSelf == false)
{
imgIcon.sprite = sprite;
imgIcon.gameObject.SetActive(true);
}
RefreshUI(amount);
}
// 刷新显示
public void RefreshUI(int amount)
{
if(amount <= 1)
{
txtAmount.gameObject.SetActive(false);
}
else
{
if (txtAmount.gameObject.activeSelf == false)
txtAmount.gameObject.SetActive(true);
txtAmount.text = "x" + amount;
}
}
}
- 创建背包UI脚本,并挂载到BagPanel上
/****************************************************
* 文件名称:BagPanel.cs
* 作 者:Blink
* 邮 箱:1614283998@qq.com
* 创建日期:2019/11/11 18:35:42
* 功 能:Noting
****************************************************/
using UnityEngine;
using UnityEngine.UI;
public class BagPanel : MonoBehaviour
{
public UIGrid[] uiGrids;
public GameObject mInfo;
private void Start()
{
// 注册背包管理器中的刷新UI回调
BagManager.Instance.OnRefreshGridUI += OnRefreshGrid;
// 获取所有的格子UI
Transform content = transform.Find("Content");
uiGrids = new UIGrid[content.childCount];
for (int i = 0; i < content.childCount; i++)
{
// 给每个格子挂载上UIGrid脚本,并初始化
uiGrids[i] = content.GetChild(i).gameObject.AddComponent<UIGrid>();
uiGrids[i].Init(i, this);
}
// 刷新所有格子的显示
var tmp = BagManager.Instance.BagGrids;
foreach (var item in tmp)
{
if(item!=null && !item.IsEmpty)
{
OnRefreshGrid(item, true);
}
}
}
// 显示物品信息,传入点击的格子所有
public void ShowInfo(int index = -1)
{
if (index != -1)
{
BagGrid grid = BagManager.Instance.FindGridByIndex(index);
if (!grid.IsEmpty)
{
BaseItem item = grid.Item;
string info = string.Format("名称:{0}\n容量:{1}\n说明:{2}", item.Name, item.Capacity, item.Des);
mInfo.GetComponentInChildren<Text>().text = info;
mInfo.SetActive(true);
}
else
{
mInfo.SetActive(false);
}
}
}
// 刷新格子显示,传入格子数据对象,isNew表示该格子是否为新添加物品(原本没有物品)
public void OnRefreshGrid(BagGrid grid, bool isNew)
{
foreach (var item in uiGrids)
{
if(item.index == grid.Index)
{
if (grid.IsEmpty)
{
item.Clear();
if (mInfo.gameObject.activeSelf)
{
mInfo.gameObject.SetActive(false);
}
}
else
{
if (isNew)
{
Sprite sprite = Resources.Load<Sprite>(grid.Item.Icon);
item.RefreshUI(sprite, grid.Amount);
}
else
{
item.RefreshUI(grid.Amount);
}
}
break;
}
}
}
}
- 创建物品数据配置表(这里使用的是Json格式)
[
{
"id":1001,
"capacity":3,
"name":"刀",
"icon":"Sprites/1001",
"type":1,
"des":"这是一件好东西"
},
{
"id": 1002,
"capacity": 3,
"name": "枪",
"icon": "Sprites/1002",
"type": 1,
"des": "这是一件好东西"
},
{
"id": 1003,
"capacity": 3,
"name": "剑",
"icon": "Sprites/1003",
"type": 1,
"des": "这是一件好东西"
},
{
"id": 1004,
"capacity": 3,
"name": "戟",
"icon": "Sprites/1004",
"type": 1,
"des": "这是一件好东西"
},
{
"id": 1005,
"capacity": 3,
"name": "斧",
"icon": "Sprites/1005",
"type": 1,
"des": "这是一件好东西"
},
{
"id": 1006,
"capacity": 3,
"name": "钺",
"icon": "Sprites/1006",
"type": 1,
"des": "这是一件好东西"
}
]
- 创建测试脚本,用来作为启动器,将其挂载到一个空物品上
/****************************************************
* 文件名称:Test.cs
* 作 者:Blink
* 邮 箱:1614283998@qq.com
* 创建日期:2019/11/11 22:38:21
* 功 能:Noting
****************************************************/
using LitJson;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
public class Test : MonoBehaviour
{
// 背包格子数量
public int gridCount = 25;
// 物品字典
private Dictionary<int, BaseItem> mItemDic = null;
private void Awake()
{
// 读取物品配置文件
LoadItemCfg();
// 加载存档数据
List<BagData> dataList = Load();
// 初始化背包管理器
BagManager.Instance.Init(gridCount, GetItem, dataList);
}
private void Update()
{
// 按Q添加物品
if (Input.GetKeyDown(KeyCode.Q))
{
int id = UnityEngine.Random.Range(1001, 1007);
BagManager.Instance.AddItem(id);
Debug.Log("添加物品,ID:" + id);
}
// 按A输出背包信息
if (Input.GetKeyDown(KeyCode.A))
{
Debug.Log(this.ToString());
}
// 按W减少物品
if (Input.GetKeyDown(KeyCode.W))
{
BagManager.Instance.SubItemByIndex(0);
Debug.Log("减少物品");
}
// 按E键存档
if (Input.GetKeyDown(KeyCode.E))
{
// 存档
Save();
}
}
private void OnGUI()
{
GUIStyle style = new GUIStyle();
style.fontSize = 30;
style.normal.textColor = Color.yellow;
GUILayout.Label("Q键添加物品",style);
GUILayout.Label("鼠标左键点击物品显示详情", style);
GUILayout.Label("鼠标右键出售物品", style);
}
// 读档
private List<BagData> Load()
{
string path = Application.streamingAssetsPath + "/bag.json";
if (File.Exists(path))
{
StreamReader reader = new StreamReader(path);
string json = reader.ReadToEnd();
reader.Close();
List<BagData> list = JsonMapper.ToObject<List<BagData>>(json);
return list;
}
else
{
return null;
}
}
// 存档
private void Save()
{
List<BagData> list = BagManager.Instance.GetBagDatas();
string json = LitJson.JsonMapper.ToJson(list);
string path = Application.streamingAssetsPath + "/bag.json";
StreamWriter writer = new StreamWriter(path);
writer.Write(json);
writer.Close();
}
// 读取配置文件
private void LoadItemCfg()
{
mItemDic = new Dictionary<int, BaseItem>();
string json = Resources.Load<TextAsset>("Configs/item").text;
LitJson.JsonData configs = LitJson.JsonMapper.ToObject(json);
foreach (LitJson.JsonData data in configs)
{
int id = int.Parse(data["id"].ToString());
int capacity = int.Parse(data["capacity"].ToString());
string name = data["name"].ToString();
string icon = data["icon"].ToString();
string des = data["des"].ToString();
BaseItem item = new BaseItem(id, name, capacity, icon, des);
mItemDic.Add(id, item);
}
}
// 获取物品数据
private BaseItem GetItem(int id)
{
if (mItemDic.ContainsKey(id))
return mItemDic[id];
return null;
}
}
效果
[
{
"Index": 0,
"ID": 1001,
"Amount": 2
},
{
"Index": 1,
"ID": 1003,
"Amount": 1
},
{
"Index": 2,
"ID": 1002,
"Amount": 2
}
]
- 读取存档效果
![《Unity:实现背包系统(二)》](https://i.loli.net/2019/11/13/JuHXrzgcKWG19RE.gif)
兄弟,什么时候出一篇关于unity的文件资源等的管理介绍,最近刚开始学习unity,对资源的管理比较混乱