Unity2D初级背包设计中篇 MVC分层撰写(万字详解)-CSDN博客、
如果你已经搞懂了中篇,那么对这个背包的拓展将极为简单,我就在这里举个例子吧
目录
1.添加物品描述信息
2.拓展思路与不足分析
1.没有删除只有丢弃功能,所以可以添加垃圾桶
2.格子有限,可以再做的大一些,也可以添加翻页功能
3.排序与分类功能
4. 逻辑层再封装
5.背包存储可以转为json而不再是让编辑器保存
1.添加物品描述信息
M层修改:
统一到SoltData之中获得
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[Serializable]
public class SlotData {
public ItemData item;
public int currentCount = 0; // 物品数量
private Action OnChange;
#region 增(Add)
// 添加物品到槽位
public void Add(int numToAdd = 1) {
this.currentCount += numToAdd;
OnChange?.Invoke();
}
// 设置槽位的物品和数量
public void AddItem(ItemData item, int count = 1) {
this.item = item;
this.currentCount = count;
OnChange?.Invoke();
}
#endregion
#region 删(Remove)
// 减少槽位中的物品数量
public void Reduce(int numToReduce = 1) {
currentCount -= numToReduce;
if (currentCount == 0) {
Clear();
}
else {
OnChange?.Invoke();
}
}
// 清空槽位
public void Clear() {
item = null;
currentCount = 0;
OnChange?.Invoke();
}
#endregion
#region 查(Check)
// 检查槽位是否为空
public bool IsEmpty() {
return currentCount == 0;
}
// 检查槽位是否可以添加物品
public bool CanAddItem() {
return currentCount < item.maxCount;
}
// 获取槽位的空余空间
public int GetFreeSpace() {
return item.maxCount - currentCount;
}
#endregion
#region 改(Update)
// 移动槽位数据
public void MoveSlot(SlotData data) {
this.item = data.item;
this.currentCount = data.currentCount;
OnChange?.Invoke();
}
// 添加监听器
public void AddListener(Action OnChange) {
this.OnChange = OnChange;
}
//获取物品描述
public string GetDescription() {
return item.Description;
}
#endregion
}
V层修改:
背包UI持有该描述的组件 因此将显示和隐藏写到BagUI类
using System.Collections.Generic;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.UI;
public class BagUI : MonoBehaviour {
[SerializeField] private Button close;
[SerializeField] private GameObject BG;
[SerializeField] private GameObject slotGrid;
[SerializeField] private List<SlotUI> soltuiList = new List<SlotUI>();
[SerializeField] private TextMeshProUGUI DText;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start() {
InitElement();
InitSlotUI();
}
// Update is called once per frame
void Update() {
ColseBag();
}
public void InitElement() {
if(BG==null)
BG = transform.Find("BG").gameObject;
if (close == null)
close = transform.Find("BG/BgElement/Close").GetComponent<Button>();
if(slotGrid)
slotGrid = transform.Find("BG/SlotGrid").gameObject;
if (close != null) {
close.onClick.AddListener(() => {
if (BG != null)
BG.SetActive(!BG.activeSelf);
else {
Debug.LogWarning("没找到BG对象");
return;
}
});
}
else
Debug.LogWarning("没有加载到close按钮");
}
public void UpdataUI() {
for (int i = 0; i < InventoryManager.Instance.BagInventory.slotList.Count; i++) {
soltuiList[i].SetData(InventoryManager.Instance.BagInventory.slotList[i]);
}
}
public void InitSlotUI() {
if (slotGrid != null) {
foreach (SlotUI slotUi in slotGrid.GetComponentsInChildren<SlotUI>()) {
soltuiList.Add(slotUi);
}
}
UpdataUI();
}
public void ColseBag() {
if (Input.GetKeyDown(KeyCode.Tab))
BG.SetActive(!BG.activeSelf);
}
public void ShowDescription(string description) {
DText.gameObject.SetActive(true);
DText.text = description;
}
public void HideDescription() {
DText.gameObject.SetActive(false);
DText.text = "";
}
}
之后当鼠标移入SoltUI之后,触发上面两种方法 ,这里可以采用事件发送的方法,也可以直接去持有对象
using System;
using TMPro;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class SlotUI : MonoBehaviour,IPointerClickHandler,IPointerEnterHandler, IPointerExitHandler {
protected SlotData slotData;
protected Image icon;
protected TextMeshProUGUI num;
[SerializeField]private BagUI bagUI;
private void Start() {
icon = transform.Find("icon").GetComponent<Image>();
num = transform.Find("num").GetComponent<TextMeshProUGUI>();
}
public SlotData GetData(){
return slotData;
}
/// <summary>
/// 为该脚本上的对象赋值一个SlotData
/// </summary>
public void SetData(SlotData slotData) {
this.slotData = slotData;
//事件监听 - 订阅者
slotData.AddListener(UpdateUI2Slot);
UpdateUI2Slot();
}
/ <summary>
/ 监听对象
/ </summary>
//public void ChangeUI(){
// UpdateUI2Slot();
//}
private void UpdateUI2Slot(){
if (slotData==null || slotData.item == null || slotData.currentCount <= 0) {
icon.enabled = false;
num.enabled = false;
}
else {
icon.enabled = true;
num.enabled = true;
icon.sprite = slotData.item.itemSprite;
num.text = slotData.currentCount.ToString();
}
}
public void OnPointerClick(PointerEventData eventData) {
Debug.Log("发生了点击");
ItemMoveHandler.Instance.OnSlotClick(this);
}
public void OnPointerEnter(PointerEventData eventData) {
Debug.Log("鼠标进入");
if (slotData.item != null)
bagUI.ShowDescription(slotData.GetDescription());
}
public void OnPointerExit(PointerEventData eventData) {
Debug.Log("鼠标离开");
if (slotData.item != null)
bagUI.HideDescription();
}
}
2.拓展思路与不足分析
1.没有删除只有丢弃功能,所以可以添加垃圾桶
2.格子有限,可以再做的大一些,也可以添加翻页功能
3.排序与分类功能
这个我将会在通用背包文章之中进行详细解释
4. 逻辑层再封装
因为物品小类自有的枚举工具/消耗品/可捡起的枚举在配置上比较烦
应该做到实时判断,也就是策划只需要给物品配置 ,然后一键导入就行了
只需要:
不再需要:
5.背包存储可以转为json而不再是让编辑器保存
以上,2D初级背包结束