unity3d制作背包系统(3)–UI部分
UI这块比较大,花了挺长时间从项目中抠代码,也发现了原来项目中有这么多垃圾代码。这部分既要写代码,又要在unity3d中调整UI。
注:这篇文章下面的所有“格子”都代表UI显示上的格子,“物品”仍代表我们第一章定义的物品(itemunit)
0.总览
本文分为三个部分,第一部分主题为定义格子,第二部分为管理格子,第三部分为总的UI管理
红框内为背包系统UI在unity中的结构,黄框为背包UI的背景(与当前主题无关)
给packgrid添加Grid Layout Group来将格子排列整齐
每个格子由以下三部分组成
slot是格子的背景兼按钮,rawimage负责显示物品的贴图,text显示物品数量
1.定义格子与“手”
为了将UI的格子与存储部分中的物品槽一一对应,我们像定义物品一样定义UI格子。同时我们将描述“左键单击拿取格子中物品到鼠标”这样的逻辑放在格子上,这样可以使管理格子的UI无需处理复杂的逻辑。
“手”
鼠标拿取时,物品的图片会跟随鼠标,这就要求得有一个稍微特别的“格子”跟着鼠标移动,因此我们定义这个特别的“格子”叫mousehand
可以看到mousehand和格子slot的结构基本一样,下面所有的“鼠标持有”就代表了这个mousehand的内容物品itemunit
跟随鼠标移动
RectTransform rect;
void Update()
{
rect.position=Input.mousePosition; //跟随鼠标,当canvas的rendermode不是overlay的时候不可用
}
“手”所承载的物品及获取、设置方法
public itemunit holding=new itemunit();
bool taking = false;
public itemunit getholding()
{
return holding;
}
public void setholding(itemunit item)
{
if (!item.isempty())
{
if (holding.id != item.id)//因itemunit类是引用所以要拿个新的itemunit
holding = idtoitemunit.idtoitem(item.id, item.subid);
holding.copyinfo(item);
}
else
{
holding = new itemunit();
}
handler.setpicture(holding);//需要一个静态的ID,texture对应表
if (!holding.isempty()) taking = true;
else taking = false;
}
初始化方法
numtexthandler handler;
void Start ()
{
rect = GetComponent<RectTransform>();
handler = GetComponentInChildren<numtexthandler>();
handler.setpicture(holding);//需要一个静态的ID,texture对应表
}
刷新显示方法
public void flush()//
{
handler.setpicture(holding);//将显示的图片设置为承载的物品对应的图片
}
对承载物品进行加减数量方法
public int addnum(int num)
{
int temp= holding.addnum(num);
flush();
return temp;
}
public int subnum(int num)
{
int temp = holding.subnum(num);
flush();
return temp;
}
直接设置承载物品数量的方法
public void setnumber(int numb)
{
holding.num=numb;
flush();
}
格子
实现格子功能的类被称为slotbutton
1.下面代码中的idtoitemunit.idtoitem功能是根据给定的物品id获取对应物品的itemunit实例.
2.uicontroller代表管理格子的UI
3candrain代表该格子内的物品能否被拿完,是被创造模式物品栏使用的功能,本来应该另外做一个类继承slotbutton来实现这个功能,这是一个失败的地方
4.takeonly是该格子内的物品是否只允许从中拿取而不能放下(参见我的世界工作台UI的产出格及火炉UI的产出格),属于延伸功能,对讲解背包系统无用,同样应该用继承实现,现在此功能与原本格子的逻辑耦合在一起,难以分开。
5.格子代码中的tex,其setholding方法的功能是将给入的itemunit显示成图片及数量,可以理解为刷新UI显示。
①首先实现格子的一些显而易见的功能:
设置内容物品:
public itemunit holding;
public void setholding(itemunit ite)//设置存储物品,不会触发UI变化事件
{
if (candrain)//如果可拿完
{
if (ite == null)
{
holding = new itemunit();
}
else
{
if (!ite.isempty())
{
if (holding.id != ite.id)//因itemunit类是引用所以要拿个新的itemunit
holding = idtoitemunit.idtoitem(ite.id, ite.subid);
holding.copyinfo(ite);
}
else holding = new itemunit();
}
}
tex