背包格子类
挂载在格子的预制体上,用于创建该格子时更新该物品的数量等信息
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class BagItem : MonoBehaviour
{
public void InitItemInfo(Item info)
{
//更新道具数量
GetComponentInChildren<Text>().text = info.num.ToString();
}
}
背包管理器
包含物品类,物品列表,以及创建演示数据的函数
using System.Collections.Generic;
public class Item
{
public int id;
public int num;
}
public class BagManager: Singleton<BagManager>
{
public List<Item> items = new List<Item>();
public void InitItemsInfo()
{
for(int i = 1; i <= 100; i++)
{
Item item = new Item();
item.id = i;
item.num = i;
items.Add(item);
}
}
}
单例类
各种Manager类继承此类之后,可以方便地通过单例获取到该Manager类里的成员
public class Singleton<T> where T : new()
{
private static T _instance;
public static T Instance
{
get
{
if (_instance == null)
{
_instance = new T();
}
return _instance;
}
}
}
背包面板
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class BagPanel : BasePanel
{
static readonly string path = "Prefabs/UI/BagPanel";
public BagPanel() : base(new PanelType(path)) { }
/*-----------可配置的参数-----------*/
public int column = 4; //列数
public float itemSize = 180; //物品格子大小
public float interval = 10; //格子之间的间隙
public float viewPortHeight = 950; //窗口的高度
//记录上一次显示的最值索引,以便移除看不见的格子
int lastMinDisplayIndex;
int lastMaxDisplayIndex;
//滑动列表的容器
public RectTransform content;
//存储当前显示的物品及编号
Dictionary<int, GameObject> curDisplayItems = new Dictionary<int, GameObject>();
public void DisplayBagItem()
{
/*-----------计算可见范围-----------*/
int minDisplayIndex = (int)(content.anchoredPosition.y / (itemSize + interval)) * column; //向下取整: 0,0 190,3 950,15
int maxDisplayIndex = (int)((content.anchoredPosition.y + viewPortHeight) / (itemSize + interval)) * column + column; // 下面一栏物品,露出一点点也需要显示,所以需要多显示一行
/*-----------越界的不显示-----------*/
if (minDisplayIndex < 0)
minDisplayIndex = 0;
if (maxDisplayIndex >= BagManager.Instance.items.Count)
maxDisplayIndex = BagManager.Instance.items.Count;
/*---------显示可见范围内的格子------*/
for (int i = minDisplayIndex;i < maxDisplayIndex; i++)
{
if (curDisplayItems.ContainsKey(i)) //已显示的格子,不再重复创建
continue;
else
{
GameObject obj = PoolManager.Instance.getObject("BagItem", "Prefabs/UI/BagItem"); //未显示的格子,从池中获取
obj.transform.SetParent(content);
obj.transform.localPosition = new Vector3(i % column * (itemSize+interval), i / column * (itemSize + interval) * (-1), 0); //将格子放到正确的位置上
obj.GetComponent<BagItem>().InitItemInfo(BagManager.Instance.items[i]); //初始化格子信息
curDisplayItems[i] = obj; //将当前显示的格子按照编号录入字典
}
}
/*----------移除不可见的格子---------*/
for(int i = lastMaxDisplayIndex;i > maxDisplayIndex;i--)
{
if (curDisplayItems.ContainsKey(i))
{
PoolManager.Instance.recycleObject("BagItem", curDisplayItems[i]);
curDisplayItems.Remove(i);
}
}
for(int i = lastMinDisplayIndex;i<minDisplayIndex;i++)
{
if (curDisplayItems.ContainsKey(i))
{
PoolManager.Instance.recycleObject("BagItem", curDisplayItems[i]);
curDisplayItems.Remove(i);
}
}
lastMaxDisplayIndex = maxDisplayIndex;
lastMinDisplayIndex = minDisplayIndex;
}
public override void OnEnter()
{
BagManager.Instance.InitItemsInfo(); //生成格子的演示数据
content = panelBindingTool.GetOrAddComponentInChildren<RectTransform>("Content"); //获取容器的组件
content.sizeDelta = new Vector2(0, Mathf.CeilToInt(BagManager.Instance.items.Count / column) * (itemSize + interval)); //根据物品数目计算容器的高度(向上取整)
panelBindingTool.GetOrAddComponentInChildren<Button>("关闭").onClick.AddListener( ()=>
{
panelStack.Pop();
}
);
GameManager.instance.NonMonoUpdateMethod = DisplayBagItem; //将DisplayBagItem函数注入GameManager的Update中,实现实时更新
}
public override void OnExit()
{
panelManager.DestroyPanel(this.panelType);
}
public override void OnPause()
{
panelBindingTool.GetOrAddComponent<CanvasGroup>().blocksRaycasts = false;
}
public override void OnResume()
{
panelBindingTool.GetOrAddComponent<CanvasGroup>().blocksRaycasts = true;
}
}
效果
|