unity简单的背包制作

本文详细介绍在Unity中实现背包系统的步骤,包括添加、删除、拖拽、交换物品及背包整理等功能。通过具体代码示例,展示了如何处理物品与背包格子之间的交互,以及背包内物品的动态管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背包系统基本功能:添加物品、删除物品、拖拽物品、交换物品位置、排列物品等等。

首先在unity将背包的UI界面制作完成,如图:

 Text是用来显示当前格子物品的数量。

然后将需要生成的物品UI制作成预制物,如图所示:

 接下来上代码

1、添加物品

添加物品的时候需要注意的是(1)当前格子是否为空(2)当前格子是否有跟需要添加相同的物体(3)格子为空的时候需要按照空格子的顺序添加物体(4)当前格子有需要添加的物体时,只需要数量++

    /// <summary>
    /// 添加物品
    /// </summary>
    /// <param name="objnum"></param>
    void LoadObjs(int objnum)
    {
        switch (objnum)
        {
            case 101: //red
                GameObject objred = GameObject.Find("red");
                if (objred != null)
                {
                    int num = int.Parse(objred.transform.parent.GetChild(0).GetComponent<Text>().text);
                    num++;
                    objred.transform.parent.GetChild(0).GetComponent<Text>().text = num.ToString();
                    return;
                }

                for (int i = 0; i < bagBakcGround.transform.childCount; i++)
                {
                    if (bagBakcGround.transform.GetChild(i).childCount <= 1)  //格子为空   创建新物体
                    {
                        GameObject go = Instantiate(Resources.Load<GameObject>("objs/red"));
                        go.transform.parent = bagBakcGround.transform.GetChild(i);
                        go.transform.localPosition = new Vector3(0, 0, 0);
                        go.transform.name = "red";
                        bagBakcGround.transform.GetChild(i).GetChild(0).GetComponent<Text>().text = "1";
                        break;
                    }
                    //else  //格子不为空  添加物体数量
                    //{
                    //    if (bagBakcGround.transform.GetChild(i).GetChild(1).name == "red")
                    //    {
                    //        int num = int.Parse(bagBakcGround.transform.GetChild(i).GetChild(0).GetComponent<Text>().text);
                    //        num++;
                    //        bagBakcGround.transform.GetChild(i).GetChild(0).GetComponent<Text>().text = num.ToString();
                    //        return;
                    //    }
                    //}
                }
                break;
            case 102:  //yellow
                GameObject objyellow = GameObject.Find("yellow");
                if (objyellow != null)
                {
                    int num = int.Parse(objyellow.transform.parent.GetChild(0).GetComponent<Text>().text);
                    num++;
                    objyellow.transform.parent.GetChild(0).GetComponent<Text>().text = num.ToString();
                    return;
                }

                for (int i = 0; i < bagBakcGround.transform.childCount; i++)
                {
                    if (bagBakcGround.transform.GetChild(i).childCount <= 1)  //格子为空   创建新物体
                    {
                        GameObject go = Instantiate(Resources.Load<GameObject>("objs/yellow"));
                        go.transform.parent = bagBakcGround.transform.GetChild(i);
                        go.transform.localPosition = new Vector3(0, 0, 0);
                        go.transform.name = "yellow";
                        bagBakcGround.transform.GetChild(i).GetChild(0).GetComponent<Text>().text = "1";
                        break;
                    }
                    //else  //格子不为空  添加物体数量
                    //{
                    //    if (bagBakcGround.transform.GetChild(i).GetChild(1).name == "yellow")
                    //    {
                    //        int num = int.Parse(bagBakcGround.transform.GetChild(i).GetChild(0).GetComponent<Text>().text);
                    //        num++;
                    //        bagBakcGround.transform.GetChild(i).GetChild(0).GetComponent<Text>().text = num.ToString();
                    //        return;
                    //    }
                    //}
                }
                break;
            case 103:  //black
                GameObject objblack = GameObject.Find("black");
                if (objblack != null)
                {
                    int num = int.Parse(objblack.transform.parent.GetChild(0).GetComponent<Text>().text);
                    num++;
                    objblack.transform.parent.GetChild(0).GetComponent<Text>().text = num.ToString();
                    return;
                }

                for (int i = 0; i < bagBakcGround.transform.childCount; i++)
                {
                    if (bagBakcGround.transform.GetChild(i).childCount <= 1)  //格子为空   创建新物体
                    {
                        GameObject go = Instantiate(Resources.Load<GameObject>("objs/black"));
                        go.transform.parent = bagBakcGround.transform.GetChild(i);
                        go.transform.localPosition = new Vector3(0, 0, 0);
                        go.transform.name = "black";
                        bagBakcGround.transform.GetChild(i).GetChild(0).GetComponent<Text>().text = "1";
                        break;
                    }
                    //else  //格子不为空  添加物体数量
                    //{
                    //    if (bagBakcGround.transform.GetChild(i).GetChild(1).name == "black")
                    //    {
                    //        int num = int.Parse(bagBakcGround.transform.GetChild(i).GetChild(0).GetComponent<Text>().text);
                    //        num++;
                    //        bagBakcGround.transform.GetChild(i).GetChild(0).GetComponent<Text>().text = num.ToString();
                    //        return;
                    //    }
                    //}
                }
                break;
            default:
                break;
        }
    }

2、拖拽物品、删除物品、交换位置。

先上完整代码:

using UnityEngine;
using System.Collections;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class DragUI : MonoBehaviour,IDragHandler,IEndDragHandler
{
    public Vector2 offsetPos;

    public Transform partar;

    /// <summary>
    /// 拖拽物品
    /// </summary>
    /// <param name="eventData"></param>
    public void OnDrag(PointerEventData eventData)
    {
        transform.parent = GameObject.Find("Canvas").gameObject.transform;
        transform.position = eventData.position - offsetPos;
    }

    public void OnEndDrag(PointerEventData eventData)
    {
        //--------是否对格子物品进行丢弃------------
        if(Mathf.Abs(Vector3.Distance(transform.position, transform.parent.position)) > 180)
        {
            int num = int.Parse(partar.GetChild(0).GetComponent<Text>().text);
            num--;
            if(num > 0)
            {
                partar.GetChild(0).GetComponent<Text>().text = num.ToString();
            }
            else if(num <= 0)
            {
                partar.GetChild(0).GetComponent<Text>().text = "";
                Destroy(transform.gameObject);
                return;
            }
        }

        //---------格子物品交换-----------
        for (int i = 0; i < bagUI.Instance.bagBakcGround.transform.childCount; i++)
        {
            if(bagUI.Instance.bagBakcGround.transform.GetChild(i).childCount > 1)
            {
                if(Mathf.Abs(Vector3.Distance(transform.position, bagUI.Instance.bagBakcGround.transform.GetChild(i).GetChild(1).position)) < 2.5f)
                {
                    //----更换物品数量---
                    string targetNum = partar.GetChild(0).GetComponent<Text>().text;
                    string ChangNum = bagUI.Instance.bagBakcGround.transform.GetChild(i).GetChild(0).GetComponent<Text>().text;
                    bagUI.Instance.bagBakcGround.transform.GetChild(i).GetChild(0).GetComponent<Text>().text = targetNum;
                    partar.GetChild(0).GetComponent<Text>().text = ChangNum;

                    //----------更换物品---
                    bagUI.Instance.bagBakcGround.transform.GetChild(i).GetChild(1).GetComponent<DragUI>().partar = partar;
                    bagUI.Instance.bagBakcGround.transform.GetChild(i).GetChild(1).parent = partar;
                    partar.GetChild(1).localPosition = new Vector3(0, 0, 0);

                    transform.parent = bagUI.Instance.bagBakcGround.transform.GetChild(i);
                    transform.localPosition = new Vector3(0, 0, 0);

                    partar = transform.parent;
                    return;
                }
            }
            else if(bagUI.Instance.bagBakcGround.transform.GetChild(i).childCount <= 1)
            {
                if(Mathf.Abs(Vector3.Distance(transform.position, bagUI.Instance.bagBakcGround.transform.GetChild(i).GetChild(0).position)) < 55.0f &&
                    Mathf.Abs(Vector3.Distance(transform.position, bagUI.Instance.bagBakcGround.transform.GetChild(i).GetChild(0).position)) > 25.0f)
                {
                    string parNum = partar.GetChild(0).GetComponent<Text>().text;
                    partar.GetChild(0).GetComponent<Text>().text = "";
                    transform.parent = bagUI.Instance.bagBakcGround.transform.GetChild(i);
                    transform.localPosition = new Vector3(0, 0, 0);

                    partar = transform.parent;
                    partar.GetChild(0).GetComponent<Text>().text = parNum;
                    return;
                }
            }
        }
        transform.parent = partar;
        transform.localPosition = new Vector3(0, 0, 0);
    }

    private void Start()
    {
        partar = transform.parent;
    }
}

(1)拖拽物品

拖拽物体实现UnityEngine.EventSystems中的接口IDragHandler和IEndDragHandler

OnDrag中的transform.parent赋值是因为UI层级关系,拖拽UI到其他格子最上面,不能被层级关系遮挡。

 partar是用来存放该物品UI的父物体,拖拽结束时需要返回到拖拽前的位置。

OnEndDrag结束时

 (2)删除物品

删除物品是用当前物品的pos和格子pos通过求绝对值来判断时候已经将物品拖拽到背包界面外面来删除该物品;

如果该物品就一个,那么就直接删除物品,如果大于1那么就数量减减。

(3)交换位置

 //---------格子物品交换-----------
        for (int i = 0; i < bagUI.Instance.bagBakcGround.transform.childCount; i++)
        {
            if(bagUI.Instance.bagBakcGround.transform.GetChild(i).childCount > 1)  //如果格子不为空
            {
                if(Mathf.Abs(Vector3.Distance(transform.position, bagUI.Instance.bagBakcGround.transform.GetChild(i).GetChild(1).position)) < 2.5f)
                {
                    //----更换物品数量---
                    string targetNum = partar.GetChild(0).GetComponent<Text>().text;
                    string ChangNum = bagUI.Instance.bagBakcGround.transform.GetChild(i).GetChild(0).GetComponent<Text>().text;
                    bagUI.Instance.bagBakcGround.transform.GetChild(i).GetChild(0).GetComponent<Text>().text = targetNum;
                    partar.GetChild(0).GetComponent<Text>().text = ChangNum;

                    //----------更换物品---
                    bagUI.Instance.bagBakcGround.transform.GetChild(i).GetChild(1).GetComponent<DragUI>().partar = partar;
                    bagUI.Instance.bagBakcGround.transform.GetChild(i).GetChild(1).parent = partar;
                    partar.GetChild(1).localPosition = new Vector3(0, 0, 0);

                    transform.parent = bagUI.Instance.bagBakcGround.transform.GetChild(i);
                    transform.localPosition = new Vector3(0, 0, 0);

                    partar = transform.parent;
                    return;
                }
            }
            else if(bagUI.Instance.bagBakcGround.transform.GetChild(i).childCount <= 1)  //如果格子为空
            {
                if(Mathf.Abs(Vector3.Distance(transform.position, bagUI.Instance.bagBakcGround.transform.GetChild(i).GetChild(0).position)) < 55.0f &&
                    Mathf.Abs(Vector3.Distance(transform.position, bagUI.Instance.bagBakcGround.transform.GetChild(i).GetChild(0).position)) > 25.0f)
                {
                    string parNum = partar.GetChild(0).GetComponent<Text>().text;
                    partar.GetChild(0).GetComponent<Text>().text = "";
                    transform.parent = bagUI.Instance.bagBakcGround.transform.GetChild(i);
                    transform.localPosition = new Vector3(0, 0, 0);

                    partar = transform.parent;
                    partar.GetChild(0).GetComponent<Text>().text = parNum;
                    return;
                }
            }
        }

交换物品位置是需要考虑交换到目标的格子中是否为空。

3、排列背包物品

当背包中的物品排列杂乱无章,有的格子有物品,有的格子没有,这时就需要排列背包中的物品。

/// <summary>
    /// 整理背包
    /// </summary>
    void FinishingBag()
    {
        Dictionary<Transform, GameObject> ObjNum = new Dictionary<Transform, GameObject>();
        for (int i = 0; i < bagBakcGround.transform.childCount; i++)
        {
            if(bagBakcGround.transform.GetChild(i).GetChild(0).GetComponent<Text>().text != "")
            {
                ObjNum.Add(bagBakcGround.transform.GetChild(i).GetChild(0), bagBakcGround.transform.GetChild(i).GetChild(1).gameObject);
            }
        }

        List<Transform> ObjKey = new List<Transform>(ObjNum.Keys);

        for (int i = 0; i < bagBakcGround.transform.childCount; i++)
        {
            if(bagBakcGround.transform.GetChild(i).childCount <= 1)
            {
                if(i < ObjNum.Count)
                {
                    bagBakcGround.transform.GetChild(i).GetChild(0).GetComponent<Text>().text = ObjKey[i].GetComponent<Text>().text;
                    ObjNum[ObjKey[i]].transform.parent.GetChild(0).GetComponent<Text>().text = "";

                    ObjNum[ObjKey[i]].transform.parent = bagBakcGround.transform.GetChild(i);
                    ObjNum[ObjKey[i]].transform.GetComponent<DragUI>().partar = bagBakcGround.transform.GetChild(i);
                    bagBakcGround.transform.GetChild(i).GetChild(1).localPosition = new Vector3(0, 0, 0);
                }
            }
        }
    }

效果图如下:

<think>嗯,用户想在Unity里实现一个背包系统。首先得了解背包系统的基本组成部分,比如物品的存储、UI显示、交互逻辑这些。根据之前看到的引用资料,好像有提到使用MVC框架,还有ScriptableObject来管理物品数据。 首先,物品数据管理部分,可能需要创建一个Item类,包含名称、图标、数量这些属性。然后使用ScriptableObject来创建物品实例,这样可以在编辑器里直接配置,方便调整。引用[4]里提到的Bag脚本应该就是用来管理多个物品的列表,可能每个背包都是一个ScriptableObject的实例。 然后是UI部分,需要动态生成物品槽,每个槽显示对应的物品图标和数量。可能需要用Grid Layout Group来自动排列这些槽,确保布局整齐。当物品被拖拽时,要处理拖拽事件,比如开始拖拽时隐藏原物品的图标,结束拖拽时交换位置或者合并数量。 接着是交互逻辑,比如点击使用物品,拖拽交换位置。这里可能需要用到Unity的事件接口,比如IBeginDragHandler、IDragHandler、IEndDragHandler来处理拖拽事件。引用[3]提到的MVC框架,可能要将数据、视图和控制分开,比如Item类作为模型,SlotUI作为视图,InventoryController作为控制器,处理逻辑。 性能优化方面,动态生成大量物品槽时可能会有性能问题,可以考虑对象池来复用槽对象,减少实例化的开销。另外,数据持久化可能需要用JSON或者PlayerPrefs来保存背包状态,确保退出游戏后数据不丢失。 用户可能还关心如何扩展背包系统,比如支持不同容器如商店、仓库之间的物品交换,或者添加装备、合成等功能。这时候需要设计更复杂的交互逻辑和数据管理,可能通过事件系统来解耦各个模块。 最后,教程资源的话,引用[2]和[4]提供了视频和代码示例,用户可以参考这些资料来一步步实现。需要注意代码的结构和可维护性,比如使用ScriptableObject和MVC模式,方便后续扩展和维护。</think>### Unity背包系统实现步骤详解 #### 一、基础数据架构 1. **物品数据定义** ```csharp [CreateAssetMenu(fileName = "Item", menuName = "Inventory/Item")] public class Item : ScriptableObject { public string itemName; // 物品名称 public Sprite icon; // 显示图标 public int maxStack = 1; // 最大堆叠数 } ``` 通过ScriptableObject创建物品模板,可在Project窗口右键生成新物品[^4] 2. **背包容器设计** ```csharp [CreateAssetMenu(fileName = "Bag", menuName = "Inventory/Bag")] public class Bag : ScriptableObject { public List<ItemSlot> slots = new List<ItemSlot>(); public int capacity = 20; // 背包容量 } [System.Serializable] public class ItemSlot { public Item item; public int amount; } ``` 支持创建多个独立背包(玩家背包/商店背包) #### 二、核心功能实现 1. **UI系统搭建** - 使用Grid Layout Group自动排列物品槽 - 动态生成Slot预制件: ```csharp void CreateSlots() { foreach (var slot in bag.slots) { var slotObj = Instantiate(slotPrefab, transform); slotObj.GetComponent<SlotUI>().Setup(slot); } } ``` 2. **拖拽交互系统** ```csharp public class DraggableItem : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler { public void OnBeginDrag(PointerEventData eventData) { iconImage.raycastTarget = false; // 禁用射线检测 } public void OnDrag(PointerEventData eventData) { transform.position = Input.mousePosition; } public void OnEndDrag(PointerEventData eventData) { iconImage.raycastTarget = true; // 处理物品放置逻辑... } } ``` #### 三、进阶功能扩展 1. **数据持久化方案** ```csharp // 保存数据 string json = JsonUtility.ToJson(bag); PlayerPrefs.SetString("InventoryData", json); // 加载数据 JsonUtility.FromJsonOverwrite(json, bag); ``` 2. **背包优化技巧** - 对象池管理Slot实例 - 使用事件系统解耦交互逻辑: ```csharp public class InventoryEvent : UnityEvent<Item, int> { } public class InventoryManager : MonoBehaviour { public static InventoryEvent OnItemAdded = new InventoryEvent(); } ``` #### 四、推荐学习资源 1. 基础实现教程:[B站Unity背包系统实现教程](https://www.bilibili.com/video/BV1db411T7wK) [^2] 2. MVC架构实践:[Unity背包系统MVC实现解析](https://example.com/mvc-inventory) [^3] 3. 扩展功能案例:多容器交互、装备系统集成
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值