UI背包系统

UI背包系统

六月 04, 2022

项目练习链接

关闭打开菜单栏

1
2
3
4
5
6
public void OpenMyBag() {
if(Input.GetKeyDown(KeyCode.O)) {
isOpen = !bag.activeSelf;
bag.SetActive(isOpen);
}
}

Grid Layerout Group

他的子节点将会被填充到格子中
在这里插入图片描述
在这里插入图片描述

UI栏 的初始化

如果游戏默认开始物品栏是关闭的一定要记住先要初始化。

ScriptableObject

经常配合CreateAssetMenu使用

1
2
3
4
5
6
7
8
9
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[CreateAssetMenu(fileName = "New Bag",menuName = "Inventory/New Bag")]
public class CreateBag : ScriptableObject
{
// Start is called before the first frame update
public List<CreateItem> items = new List<CreateItem>();
}

显示物品栏物体

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class InventoryManager : MonoBehaviour
{
public static InventoryManager instance;

public CreateBag myBag;
public GameObject slotGrid;
// public Slot slotPrefab;
public GameObject emptySlot;
public Text itemInfromation;

public List<GameObject> slots = new List<GameObject>();//管理生成的18个slots

void Awake()
{
if (instance != null)
Destroy(this);
instance = this;
}

private void OnEnable()
{
RefreshItem();
instance.itemInfromation.text = "";
}

public static void UpdateItemInfo(string itemDescription)
{
instance.itemInfromation.text = itemDescription;
}

/*public static void CreateNewItem(Item item)
{
Slot newItem = Instantiate(instance.slotPrefab, instance.slotGrid.transform.position, Quaternion.identity);
newItem.gameObject.transform.SetParent(instance.slotGrid.transform);
newItem.slotItem = item;
newItem.slotImage.sprite = item.itemImage;
newItem.slotNum.text = item.itemHeld.ToString();
}*/

public static void RefreshItem()
{
//循环删除slotGrid下的子集物体
for (int i = 0; i < instance.slotGrid.transform.childCount; i++)
{
if (instance.slotGrid.transform.childCount == 0)
break;
Destroy(instance.slotGrid.transform.GetChild(i).gameObject);
instance.slots.Clear();
}

//重新生成对应myBag里面的物品的slot
for (int i = 0; i < instance.myBag.items.Count; i++)
{
// CreateNewItem(instance.myBag.itemList[i]);
instance.slots.Add(Instantiate(instance.emptySlot));
instance.slots[i].transform.SetParent(instance.slotGrid.transform);
instance.slots[i].GetComponent<Slot>().slotID = i;
instance.slots[i].GetComponent<Slot>().SetupSlot(instance.myBag.items[i]);
}
}
}

拖拽物品

CanvasGroup

在这里插入图片描述

1
GetComponent<CanvasGroup>().blocksRaycasts = false;

射线阻挡关闭,开启对ui面板的碰撞

事件系统的接口

1
2
3
4
5
IBeginDragHandler, IDragHandler, IEndDragHandler//接口
//接口提供的方法
public void OnBeginDrag(PointerEventData eventData);
public void OnDrag(PointerEventData eventData);
public void OnEndDrag(PointerEventData eventData);

在OnEndDrag方法最后一定要射线阻挡开启,不然无法再次选中移动的物品
ItemOnDrag的代码

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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;

public class ItemOnDrag : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
public Transform originalParent;
public CreateBag myBag;
private int currentItemID;//当前物品ID

public void OnBeginDrag(PointerEventData eventData)
{
originalParent = transform.parent;
currentItemID = originalParent.GetComponent<Slot>().slotID;
transform.SetParent(transform.parent.parent);
transform.position = eventData.position;
GetComponent<CanvasGroup>().blocksRaycasts = false;//射线阻挡关闭
}

public void OnDrag(PointerEventData eventData)
{
transform.position = eventData.position;
//Debug.Log(eventData.pointerCurrentRaycast.gameObject.name);//输出鼠标当前位置下到第一个碰到到物体名字
}

public void OnEndDrag(PointerEventData eventData) {


if(eventData.pointerCurrentRaycast.gameObject==null) {
transform.SetParent(originalParent.transform);
transform.position = originalParent.transform.position;
}else if (eventData.pointerCurrentRaycast.gameObject.name == "Item Image")//判断下面物体名字是:Item Image 那么互换位置
{
transform.SetParent(eventData.pointerCurrentRaycast.gameObject.transform.parent.parent);
transform.position = eventData.pointerCurrentRaycast.gameObject.transform.parent.parent.position;
//itemList的物品存储位置改变
var temp = myBag.items[currentItemID];
myBag.items[currentItemID] = myBag.items[eventData.pointerCurrentRaycast.gameObject.GetComponentInParent<Slot>().slotID];
myBag.items[eventData.pointerCurrentRaycast.gameObject.GetComponentInParent<Slot>().slotID] = temp;

eventData.pointerCurrentRaycast.gameObject.transform.parent.position = originalParent.position;
eventData.pointerCurrentRaycast.gameObject.transform.parent.SetParent(originalParent);
}
else if (eventData.pointerCurrentRaycast.gameObject.name == "slot(Clone)") {
//否则直接挂在检测到到Slot下面
transform.SetParent(eventData.pointerCurrentRaycast.gameObject.transform);
transform.position = eventData.pointerCurrentRaycast.gameObject.transform.position;

//itemList的物品存储位置改变
myBag.items[eventData.pointerCurrentRaycast.gameObject.GetComponentInParent<Slot>().slotID] = myBag.items[currentItemID];
myBag.items[currentItemID] = null;

}
else {

transform.SetParent(originalParent.transform);
transform.position = originalParent.transform.position;
}
GetComponent<CanvasGroup>().blocksRaycasts = true;//射线阻挡开启,不然无法再次选中移动的物品
}
}

详情见项目

敌方血条显示

血条在空间显示

血条显示在角色的正上方,将Canvas的渲染模式修改为世界空间坐标下,在角色正上方建立一个空物件,标识血条出现的位置用代码实现同步。

图标始终面向摄像头

1
Target.transform.forward = - Camera.main.transform.forward;