GameUI搭建

Game UI

UI结构

  1. HP血条是通过动态增删LifeItem图片实现的
  2. 右下角为护盾和炸弹,需要添加特效,还需要添加左手右手模式。

在Prefab文件夹内,新建UI文件夹,将UI的Prefab全部转移进去,并修改Pathes里面的路径

Pathes中添加UIPrefab路径和创建GameUIControllerGameUIView的部分略。注意要创建在Scripts——UI——GameUI文件夹内。

Const

在Const中添加玩家最大生命值常量,以及LifeItem最大显示数量。

1
2
3
//游戏中部分常量数据
public const int LIFE_MAX = 100;
public const int LIFE_ITEM_NUM = 10;

GameUIView

只有根节点上的UI脚本才会使用“View”做结尾。

1
2
3
4
5
6
7
8
[BindPrefab(Pathes.GAMEUI_VIEW,Consts.BIND_PREFAB_PRIORITY_VIEW)]
public class GameUIView : ViewBase
{
protected override void InitChild()
{
UIUtil.Get("Life").AddCo<Life>();
}
}

GameUIController

1
2
3
4
5
6
7
8
[BindPrefab(Pathes.GAMEUI_VIEW,Consts.BIND_PREFAB_PRIORITY_CONTROLLER)]
public class GameUIController : ControllerBase
{
protected override void InitChild()
{
transform.Find("Life").gameObject.AddComponent<LifeController>();
}
}

Life

Life脚本需要动态挂载在GameUI——Life节点上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
using System.Collections.Generic;
using UnityEngine;

public class Life : ViewBase, IReceiver
{
private List<LifeItem> _items;
protected override void InitChild()
{
_items = new();
InitItem();
UpdateLife();
}
public override void Show()
{
base.Show();
MessageMgr.Instance.AddListener(MsgEvent.EVENT_HP, this);
}
public override void Hide()
{
base.Hide();
MessageMgr.Instance.RemoveListener(MsgEvent.EVENT_HP, this);
}
private void InitItem()
{
GameObject item;
for (int i = 0; i < Consts.LIFE_ITEM_NUM; i++)
{
item = LoadMgr.Instance.LoadPrefabAndInstantiate(Pathes.LIFE_ITEM,transform);
item.name = i.ToString();
_items.Add(item.AddComponent<LifeItem>());
}
}
private void UpdateLife()
{
UIUtil.Get("Value").SetText(GameModel.Instance.Life);
}

public void ReceiveMessage(params object[] args)
{
UpdateLife();
}
}

Life脚本继承IReceiver,接入消息系统。

通过InitItem动态添加LifeItem。

每次动态生成一个LifeItem,都修改一下生成的这个Item的name,把它的id作为name,传给LifeItem

UpdateLife方法交给消息系统来更新,消息系统的实现在下一节。

LifeController

LifeController

1
2
3
4
5
6
public class LifeController : ControllerBase
{
protected override void InitChild()
{
}
}

GameModel

在Scripts——Model文件夹内新建GameModel脚本,这个脚本存储运行时的玩家生命值和得分数据等。

1
2
3
4
5
6
public class GameModel : NormalSingleton<GameModel> 
{
public int Life { get; set; }
public int Score { get; set; }
public int Stars { get; set; }
}

LifeItem

LifeItem是动态加载到Life节点下的LifeItem预制体上挂载的脚本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
using UnityEngine;

public class LifeItem : ViewBase, IReceiver
{
private int _lifeMin;//当前Item所代表的生命最小值
protected override void InitChild()
{
int id = int.Parse(transform.name);
SetItemPos(id);
_lifeMin = GetLifeMin(id);
}
public override void Show()
{
base.Show();
MessageMgr.Instance.AddListener(MsgEvent.EVENT_HP, this);
}
public override void Hide()
{
base.Hide();
MessageMgr.Instance.RemoveListener(MsgEvent.EVENT_HP, this);
}
private int GetLifeMin(int id)
{
int eachLife = Consts.LIFE_MAX / Consts.LIFE_ITEM_NUM;
return id * eachLife;
}
private void SetItemPos(int id)
{
RectTransform rectTrans = transform.GetRect();
float width = rectTrans.rect.height;
Vector2 pos = rectTrans.anchoredPosition;
pos.x = width / 2 + width * id;
rectTrans.anchoredPosition = pos;
}
public void ReceiveMessage(params object[] args)
{
if (GameModel.Instance.Life < _lifeMin)
{
Hide();
}
}
}

每个LifeItem都是代表10点生命值的块,注意每个LifeItem的Prefab都旋转了90度,所以我们通过Height值来计算下一个LifeItem的位置。

LifeItem继承IReceiver,接入消息系统,使用消息系统来更新自己的显示。消息系统在下一节。