
背包系统目前完成了三节课内容:
1. UGUI界面拼接
2. 存储框架的设计
3. 界面和逻辑书写
有些同学遇到了bug但是不知道怎么排查,因此这里把前三节课涉及到的代码部分贴出来,方便大家对照。

工程项目等整个课程完结会发出来,前三节课的工程先放在知识星球,见文末。
静态数据:配置的物品id、名称、图片路径
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(menuName = "XiaoQi/PackageTable", fileName = "PackageTable")]
public class PackageTable : ScriptableObject
{
public List<PackageTableItem> DataList = new List<PackageTableItem>();
}
[System.Serializable]
public class PackageTableItem
{
public int id;
public int type;
public int star;
public string name;
public string description;
public string skillDescription;
public string imagePath;
}
动态数据:物品的等级数量等信息
using UnityEngine;
using System.Collections.Generic;
public class PackageLocalData
{
private static PackageLocalData _instance;
public static PackageLocalData Instance
{
get
{
if (_instance == null)
{
_instance = new PackageLocalData();
}
return _instance;
}
}
public List<PackageLocalItem> items;
public void SavePackage()
{
string inventoryJson = JsonUtility.ToJson(this);
PlayerPrefs.SetString("PackageLocalData", inventoryJson);
PlayerPrefs.Save();
}
public List<PackageLocalItem> LoadPackage()
{
if (items != null)
{
return items;
}
if (PlayerPrefs.HasKey("PackageLocalData"))
{
string inventoryJson = PlayerPrefs.GetString("PackageLocalData");
PackageLocalData packageLocalData = JsonUtility.FromJson<PackageLocalData>(inventoryJson);
items = packageLocalData.items;
return items;
}
else
{
items = new List<PackageLocalItem>();
return items;
}
}
}
[System.Serializable]
public class PackageLocalItem
{
public string uid;
public int id;
public int num;
public int level;
public bool isNew;
public override string ToString()
{
return string.Format("[id]:{0} [num]:{1}", id, num);
}
}
逻辑类、整个游戏的管理者和中枢
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameManager : MonoBehaviour
{
private static GameManager _instance;
private PackageTable packageTable;
private void Awake()
{
_instance = this;
DontDestroyOnLoad(gameObject);
}
public static GameManager Instance
{
get
{
return _instance;
}
}
// Start is called before the first frame update
void Start()
{
UIManager.Instance.OpenPanel(UIConst.PackagePanel);
// print(GetPackageLocalData().Count);
// print(GetPackageTable().DataList.Count);
}
public PackageTable GetPackageTable()
{
if (packageTable == null)
{
packageTable = Resources.Load<PackageTable>("TableData/PackageTable");
}
return packageTable;
}
public List<PackageLocalItem> GetPackageLocalData()
{
return PackageLocalData.Instance.LoadPackage();
}
public PackageTableItem GetPackageItemById(int id)
{
List<PackageTableItem> packageDataList = GetPackageTable().DataList;
foreach (PackageTableItem item in packageDataList)
{
if (item.id == id)
{
return item;
}
}
return null;
}
public PackageLocalItem GetPackageLocalItemByUId(string uid)
{
List<PackageLocalItem> packageDataList = GetPackageLocalData();
foreach (PackageLocalItem item in packageDataList)
{
if (item.uid == uid)
{
return item;
}
}
return null;
}
public List<PackageLocalItem> GetSortPackageLocalData()
{
List<PackageLocalItem> localItems = PackageLocalData.Instance.LoadPackage();
localItems.Sort(new PackageItemComparer());
return localItems;
}
}
public class PackageItemComparer : IComparer<PackageLocalItem>
{
public int Compare(PackageLocalItem a, PackageLocalItem b)
{
PackageTableItem x = GameManager.Instance.GetPackageItemById(a.id);
PackageTableItem y = GameManager.Instance.GetPackageItemById(b.id);
// 首先按star从大到小排序
int starComparison = y.star.CompareTo(x.star);
// 如果star相同,则按id从大到小排序
if (starComparison == 0)
{
int idComparison = y.id.CompareTo(x.id);
if (idComparison == 0)
{
return b.level.CompareTo(a.level);
}
return idComparison;
}
return starComparison;
}
}
界面的基类
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BasePanel : MonoBehaviour
{
protected bool isRemove = false;
protected new string name;
protected virtual void Awake()
{
}
public virtual void SetActive(bool active)
{
gameObject.SetActive(active);
}
public virtual void OpenPanel(string name)
{
this.name = name;
SetActive(true);
}
public virtual void ClosePanel()
{
isRemove = true;
SetActive(false);
Destroy(gameObject);
if (UIManager.Instance.panelDict.ContainsKey(name))
{
UIManager.Instance.panelDict.Remove(name);
}
}
}
界面管理器
using System.Collections;
using System.Collections.Generic;
using System;
using UnityEngine;
public class UIManager
{
private static UIManager _instance;
private Transform _uiRoot;
// 路径配置字典
private Dictionary<string, string> pathDict;
// 预制件缓存字典
private Dictionary<string, GameObject> prefabDict;
// 已打开界面的缓存字典
public Dictionary<string, BasePanel> panelDict;
public static UIManager Instance
{
get
{
if (_instance == null)
{
_instance = new UIManager();
}
return _instance;
}
}
public Transform UIRoot
{
get
{
if (_uiRoot == null)
{
if (GameObject.Find("Canvas"))
{
_uiRoot = GameObject.Find("Canvas").transform;
}
else
{
_uiRoot = new GameObject("Canvas").transform;
}
};
return _uiRoot;
}
}
private UIManager()
{
InitDicts();
}
private void InitDicts()
{
prefabDict = new Dictionary<string, GameObject>();
panelDict = new Dictionary<string, BasePanel>();
pathDict = new Dictionary<string, string>()
{
{UIConst.PackagePanel, "Package/PackagePanel"},
};
}
public BasePanel GetPanel(string name)
{
BasePanel panel = null;
// 检查是否已打开
if (panelDict.TryGetValue(name, out panel))
{
return panel;
}
return null;
}
public BasePanel OpenPanel(string name)
{
BasePanel panel = null;
// 检查是否已打开
if (panelDict.TryGetValue(name, out panel))
{
Debug.Log("界面已打开: " + name);
return null;
}
// 检查路径是否配置
string path = "";
if (!pathDict.TryGetValue(name, out path))
{
Debug.Log("界面名称错误,或未配置路径: " + name);
return null;
}
// 使用缓存预制件
GameObject panelPrefab = null;
if (!prefabDict.TryGetValue(name, out panelPrefab))
{
string realPath = "Prefab/Panel/" + path;
panelPrefab = Resources.Load<GameObject>(realPath) as GameObject;
prefabDict.Add(name, panelPrefab);
}
// 打开界面
GameObject panelObject = GameObject.Instantiate(panelPrefab, UIRoot, false);
panel = panelObject.GetComponent<BasePanel>();
panelDict.Add(name, panel);
panel.OpenPanel(name);
return panel;
}
public bool ClosePanel(string name)
{
BasePanel panel = null;
if (!panelDict.TryGetValue(name, out panel))
{
Debug.Log("界面未打开: " + name);
return false;
}
panel.ClosePanel();
// panelDict.Remove(name);
return true;
}
}
public class UIConst
{
// menu panels
public const string PackagePanel = "PackagePanel";
}
背包界面主体逻辑
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PackagePanel : BasePanel
{
private Transform UIMenu;
private Transform UIMenuWeapon;
private Transform UIMenuFood;
private Transform UITabName;
private Transform UICloseBtn;
private Transform UICenter;
private Transform UIScrollView;
private Transform UIDetailPanel;
private Transform UILeftBtn;
private Transform UIRightBtn;
private Transform UIDeletePanel;
private Transform UIDeleteBackBtn;
private Transform UIDeleteInfoText;
private Transform UIDeleteConfirmBtn;
private Transform UIBottomMenus;
private Transform UIDeleteBtn;
private Transform UIDetailBtn;
public GameObject PackageUIItemPrefab;
override protected void Awake()
{
base.Awake();
InitUI();
}
private void Start() {
RefreshUI();
}
private void InitUI()
{
InitUIName();
InitClick();
}
private void RefreshUI()
{
RefreshScroll();
}
private void RefreshScroll()
{
// 清理滚动容器中原本的物品
RectTransform scrollContent = UIScrollView.GetComponent<ScrollRect>().content;
for (int i = 0; i < scrollContent.childCount; i++)
{
Destroy(scrollContent.GetChild(i).gameObject);
}
foreach (PackageLocalItem localData in GameManager.Instance.GetSortPackageLocalData())
{
Transform PackageUIItem = Instantiate(PackageUIItemPrefab.transform, scrollContent) as Transform;
PackageCell packageCell = PackageUIItem.GetComponent<PackageCell>();
packageCell.Refresh(localData, this);
}
}
private void InitUIName()
{
UIMenu = transform.Find("TopCenter/Menu");
UIMenuWeapon = transform.Find("TopCenter/Menus/Weapon");
UIMenuFood = transform.Find("TopCenter/Menus/Food");
UITabName = transform.Find("LeftTop/TabName");
UICloseBtn = transform.Find("RightTop/Close");
UICenter = transform.Find("Center");
UIScrollView = transform.Find("Center/Scroll View");
UIDetailPanel = transform.Find("Center/DetailPanel");
UILeftBtn = transform.Find("Left/Button");
UIRightBtn = transform.Find("Right/Button");
UIDeletePanel = transform.Find("Bottom/DeletePanel");
UIDeleteBackBtn = transform.Find("Bottom/DeletePanel/Back");
UIDeleteInfoText = transform.Find("Bottom/DeletePanel/InfoText");
UIDeleteConfirmBtn = transform.Find("Bottom/DeletePanel/ConfirmBtn");
UIBottomMenus = transform.Find("Bottom/BottomMenus");
UIDeleteBtn = transform.Find("Bottom/BottomMenus/DeleteBtn");
UIDetailBtn = transform.Find("Bottom/BottomMenus/DetailBtn");
UIDeletePanel.gameObject.SetActive(false);
UIBottomMenus.gameObject.SetActive(true);
}
private void InitClick()
{
UIMenuWeapon.GetComponent<Button>().onClick.AddListener(OnClickWeapon);
UIMenuFood.GetComponent<Button>().onClick.AddListener(OnClickFood);
UICloseBtn.GetComponent<Button>().onClick.AddListener(OnClickClose);
UILeftBtn.GetComponent<Button>().onClick.AddListener(OnClickLeft);
UIRightBtn.GetComponent<Button>().onClick.AddListener(OnClickRight);
UIDeleteBackBtn.GetComponent<Button>().onClick.AddListener(OnDeleteBack);
UIDeleteConfirmBtn.GetComponent<Button>().onClick.AddListener(OnDeleteConfirm);
UIDeleteBtn.GetComponent<Button>().onClick.AddListener(OnDelete);
UIDetailBtn.GetComponent<Button>().onClick.AddListener(OnDetail);
}
private void OnClickWeapon()
{
print(">>>>> OnClickWeapon");
}
private void OnClickFood()
{
print(">>>>> OnClickFood");
}
private void OnClickClose()
{
print(">>>>> OnClickClose");
ClosePanel();
// UIManager.Instance.ClosePanel(UIConst.PackagePanel);
}
private void OnClickLeft()
{
print(">>>>> OnClickLeft");
}
private void OnClickRight()
{
print(">>>>> OnClickRight");
}
private void OnDeleteBack()
{
print(">>>>> onDeleteBack");
}
private void OnDeleteConfirm()
{
print(">>>>> OnDeleteConfirm");
}
private void OnDelete()
{
print(">>>>> OnDelete");
}
private void OnDetail()
{
print(">>>>> OnDetail");
}
}
背包中单个物品的代码逻辑
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class PackageCell : MonoBehaviour
{
private Transform UIIcon;
private Transform UIHead;
private Transform UINew;
private Transform UISelect;
private Transform UILevel;
private Transform UIStars;
private Transform UIDeleteSelect;
private PackageLocalItem packageLocalData;
private PackageTableItem packageTableItem;
private PackagePanel uiParent;
private void Awake()
{
InitUIName();
}
private void InitUIName()
{
UIIcon = transform.Find("Top/Icon");
UIHead = transform.Find("Top/Head");
UINew = transform.Find("Top/New");
UILevel = transform.Find("Bottom/LevelText");
UIStars = transform.Find("Bottom/Stars");
UISelect = transform.Find("Select");
UIDeleteSelect = transform.Find("DeleteSelect");
UIDeleteSelect.gameObject.SetActive(false);
}
public void Refresh(PackageLocalItem packageLocalData, PackagePanel uiParent)
{
// 数据初始化
this.packageLocalData = packageLocalData;
this.packageTableItem = GameManager.Instance.GetPackageItemById(packageLocalData.id);
this.uiParent = uiParent;
// 等级信息
UILevel.GetComponent<Text>().text = "Lv." + this.packageLocalData.level.ToString();
// 是否是新获得?
UINew.gameObject.SetActive(this.packageLocalData.isNew);
// 物品的图片
Texture2D t = (Texture2D)Resources.Load(this.packageTableItem.imagePath);
Sprite temp = Sprite.Create(t, new Rect(0, 0, t.width, t.height), new Vector2(0, 0));
UIIcon.GetComponent<Image>().sprite = temp;
// 刷新星级
RefreshStars();
}
public void RefreshStars()
{
for (int i = 0; i < UIStars.childCount; i++)
{
Transform star = UIStars.GetChild(i);
if (this.packageTableItem.star > i)
{
star.gameObject.SetActive(true);
}
else
{
star.gameObject.SetActive(false);
}
}
}
}
工程项目等整个课程完结会发出来,前三节课的工程项目放在知识星球里啦,欢迎加入。
