游戏开发中常见系统梳理之背包系统的实现一

游戏中几乎都存在大大小小的背包系统,接下来我将讲述背包系统具体是如何实现的(完整源码)

以下是使用unity+NGUI实现(使用txt配置的方法,后续更新UGUI+Json实现的背包系统敬请期待!)

背包中的物品我们常常将其制作成预设体,通过改变预设体图片来产生不同的物品,以下是物品以及管理格子系统的逻辑:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using static UnityEditor.Progress;

/// <summary>
/// 一个用于控制背包內物品的类
/// </summary>

public class InventoryItem : UIDragDropItem
{
    //关联物品的图片
    public UISprite sprite;
    private int id;
    //关联显示窗口
    public UISprite tipWindow1;
    public UIButton tipbtnOk;
    public UIButton tipbtnCancel;
    
    void Update()
    {

        if (isHover)
        {
            //显示提示信息
           InventoryDes._instance.Show(id);
            if(Input.GetMouseButtonDown(1))
            {
                //按下鼠标右键开始穿戴
                //显示窗口
                tipWindow1.gameObject.SetActive(true);
                tipbtnOk.onClick.Add(new EventDelegate(() =>
                {
                    bool success = EquipmentUI._instance.Dress(id);
                    if(success)
                    {
                        transform.parent.GetComponent<InventoryItemGrid>().MinusNumber();
                    }
                    tipWindow1.gameObject.SetActive(false);
                }));
                tipbtnCancel.onClick.Add(new EventDelegate(() =>
                {
                    tipWindow1.gameObject.SetActive(false);
                }));
               

            }
        }
    }
  

    protected override void OnDragDropRelease(GameObject surface)
    {
        base.OnDragDropRelease(surface);

        //测试
        if (surface != null)
        {
            if (surface.tag == Tags.inventory_item_grid)
            {
                //拖放至空格子里面
                if (surface == this.transform.parent.gameObject)
                {
                    //拖放在自己的格子里面

                }
                else
                {
                    InventoryItemGrid oldParent = this.transform.parent.GetComponent<InventoryItemGrid>();

                    this.transform.parent = surface.transform;
                    //zhuyi
                    ResetPosition();
                    InventoryItemGrid newParent = surface.GetComponent<InventoryItemGrid>();

                    newParent.SetId(oldParent.id, oldParent.num);
                    oldParent.ClearInfo();
                }

            }
            else if (surface.tag == Tags.inventory_item)
            {
                //拖放在有物品的格子里面
                InventoryItemGrid grid1 = this.transform.parent.GetComponent<InventoryItemGrid>();
                InventoryItemGrid grid2 = surface.transform.parent.GetComponent<InventoryItemGrid>();
                int id = grid1.id; int num = grid1.num;

                grid1.SetId(grid2.id, grid2.num);
                grid2.SetId(id, num);
            }
            else if(surface.tag==Tags.shortcut)
            {
                //拖动到快捷栏当中
                surface.GetComponent<ShortCutGrid>().SetInventory(id);
               
            }
        }
        else
        {

        }
        ResetPosition();
    }
    //重置位置
    void ResetPosition()
    {
        transform.localPosition = Vector3.zero;
    }

    //注意这里
    //public void SetId(int id)
    //{
    //    ObjectInfo info=ObjectsInfo._instance.GetObjectInfoById(id);
    //    sprite.spriteName = info.icon_name;
    //}
    public void SetIconName(int id, string icon_name)
    {
        sprite.spriteName = icon_name;
        this.id = id;
    }
    //public void SetIconName(string icon_name)
    //{
    //    if (icon_name == null)
    //    {
    //        sprite.spriteName = "Icon-potion1";
    //        Debug.Log("null");
    //    }
    //    else
    //         Debug.Log("NOT NULL" + icon_name);
    //     // sprite.spriteName = icon_name;
    //}
    private bool isHover = false;
    public void OnHoverOver()
    {
        isHover = true;
    }
    public void OnHoverOut()
    {
        isHover = false;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 一个用于管理背包內所有格子的类
/// </summary>
public class Inventory : MonoBehaviour
{
    public static Inventory _instance;
    private TweenPosition tween;
    //定义金币的数量 初始化为1000
    private int coinCount = 1000;
    //使用List将格子们存储起来
    public List<InventoryItemGrid> itemGridList = new List<InventoryItemGrid>();
    //关联金币文本,控制数量
    public UILabel coinNumberLabel;
    public GameObject inventoryItem;
    //关联背包的显示和隐藏(按钮)
    public UIButton btnBag;
    public UIButton btnClose;
    private bool isShow=false;

    void Awake()
    {
        _instance = this;
        tween=this.GetComponent<TweenPosition>();
    }
    private void Start()
    {
        btnBag.onClick.Add(new EventDelegate(() =>
        {
            Show();
        }));
        btnClose.onClick.Add(new EventDelegate(() =>
        {
            Hide();
        }));
    }
    public void Show()
    {
        isShow=true;
        tween.PlayForward();
    }
    public void Hide()
    {
        isShow=false;
        tween.PlayReverse();
    }
    public void TransformState()
    {
        if(isShow==false)
        {
            Show();
        }
        else
        {
            Hide();
        }

    }
    //增加金币的方法
    public void AddCoin(int count)
    {
        coinCount += count;
        coinNumberLabel.text = coinCount.ToString();//更新金币的显示
    }

    //取款方法
    public bool GetCoin(int count)
    {
        if(coinCount>=count)
        {
            coinCount-=count;
            coinNumberLabel.text = coinCount.ToString();//更新金币显示
            return true;
        }
        return false;
    }

    //测试背包系统的方法
    void Update()
    {
        if (Input.GetKeyDown(KeyCode.X))
        {
            GetId(Random.Range(2001,2023));
        }
    }

    //拾取到物品 添加到物品栏里面
    //处理拾取物品的功能
    public void GetId(int id,int count=1)
    {
        //查找所有物品中是否存在该物品
        //存在就数量+1

         InventoryItemGrid grid = null;
        foreach (InventoryItemGrid temp in itemGridList)
        {
            if (temp.id == id)
            {
                grid = temp;
                break;
            }
        }
        if (grid != null)
        {
            grid.PlusNumber(count);
        }
        else
        {
            //不存在的情况
            foreach (InventoryItemGrid temp in itemGridList)
            {
                if (temp.id == 0)
                {
                    grid = temp;
                    break;
                }
            }
            //不存在就放在空的格子里面
            if (grid != null)
            {
                GameObject itemGo = NGUITools.AddChild(grid.gameObject, inventoryItem);
                itemGo.transform.localPosition = Vector3.zero;
                itemGo.GetComponent<UISprite>().depth = 4;
                grid.SetId(id,count);
            }
        }
    }

    public bool MinusId(int id,int count=1)
    {
       
        InventoryItemGrid grid=null;
        foreach(InventoryItemGrid temp in itemGridList)
        {
            if (temp.id == id)
            {
                grid = temp;
                break;
            }
        }
        if (grid == null)
        { 
            return false; 
        }
        else
        {
            bool isSuccess = grid.MinusNumber(count);
            return isSuccess;
        }
    }
}

与物品相关的就是物品的描述了,将鼠标移动到物品上面时就会显示物品的信息,那么物品显示又应该怎么制作呢?废话不多说,直接上代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 一个用于控制物品信息显示的类
/// </summary>
public class InventoryDes : MonoBehaviour
{
    public static InventoryDes _instance;
    public UILabel label;
    //计时器
    private float timer = 0;

    void Awake()
    {
        _instance = this;

        this.gameObject.SetActive(false);
    }
    void Update()
    {
        if (this.gameObject.activeInHierarchy == true)
        {
            timer -= Time.deltaTime;
            if (timer <= 0)
            {
                this.gameObject.SetActive(false);
            }
        }
    }
    //显示的方法
    public void Show(int id)
    {
        this.gameObject.SetActive(true);
        timer = 0.1f;
        transform.position = UICamera.currentCamera.ScreenToWorldPoint(Input.mousePosition);
        ObjectInfo info = ObjectsInfo._instance.GetObjectInfoById(id);
        string des = "";
        switch (info.type)
        {
            case ObjectType.Drug:
                des = GetDrugDes(info);
                break;
            case ObjectType.Equip:
                des = GetEquipDes(info);
                break;
        }
        //更新显示
        label.text = des;
    }
    string GetDrugDes(ObjectInfo info)
    {
        string str = "";
        str +="名称:" + info.name + "\n";
        str += "+HP:" + info.hp + "\n";
        str += "+MP:" + info.mp + "\n";
         str += "出售价:" + info.price_sell + "\n";
        str += "购买价:" + info.price_buy;
        return str;
    }

    string GetEquipDes(ObjectInfo info)
    {
        string str = "";
        str += "名称" + info.name + "\n";
        switch(info.dressType)
        {
            case DressType.Headgear:
                str += "穿戴类型:头盔\n";
                break;
            case DressType.Armor:
                str += "穿戴类型:盔甲\n";
                break;
            case DressType.LeftHand:
                str += "穿戴类型:左手\n";
                break;
           case DressType.RightHand:
                str += "穿戴类型:右手\n";
                break;
            case DressType.Shoe:
                str += "穿戴类型:鞋\n";
                break;
            case DressType.Accessory:
                str += "穿戴类型:饰品\n";
                break;

        }
        switch(info.applicationType)
        {
            case ApplicationType.Swordman:
                str += "适用类型:剑士\n";
                break;
            case ApplicationType.Magician:
                str += "适用类型:魔法师\n";
                break;
            case ApplicationType.Common:
                str += "适用类型:通用\n";
                break;
        }
        str += "伤害值:" + info.attack + "\n";
        str += "防御值:" + info.def + "\n";
        str += "速度值:" + info.speed + "\n";
        return str;
    }
}

格子的逻辑:
 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 一个用于控制背包单个格子的类
/// </summary>
public class InventoryItemGrid : MonoBehaviour
{
    public static InventoryItemGrid _instance;
    public int id = 0;
    private ObjectInfo info = null;
    public int num = 0;
    public UILabel numLabel;

    void Awake()
    {
        _instance = this;
        //一开始隐藏文本
        numLabel.enabled= false;
    }

    public void SetId(int id, int num = 1)
    {
        this.id = id;
        info = ObjectsInfo._instance.GetObjectInfoById(id);

       InventoryItem item = this.GetComponentInChildren<InventoryItem>();

      
        item.SetIconName(id, info.icon_name);
       
            numLabel.enabled = true;
        this.num = num;
        numLabel.text = num.ToString();
    }
    public void PlusNumber(int num = 1)
    {
       
            this.num += num;
            //更新显示
            numLabel.text = this.num.ToString();
       
    }

    //用于减去数量的  表示装备是否减去成功
    public bool MinusNumber(int num=1)
    {
        
        if(this.num>=num)
        {
            this.num -= num;
            numLabel.text = this.num.ToString();
            if(this.num==0)
            {
                //清空物品
                ClearInfo();
                GameObject.Destroy(this.GetComponentInChildren<InventoryItem>().gameObject);
            }
            return true;
        }
        return false;
    }

    //public void PlusNumber(int num = 1)
    //{
    //    if (this.num < 10)
    //    {
    //        this.num = num + this.num;

    //        //更新显示
    //        numLabel.text = this.num.ToString();
    //        if (this.num <= 1)
    //            numLabel.enabled = false;
    //        else
    //            numLabel.enabled = true;
    //    }
    //}
    //设置一个清空的方法
    public void ClearInfo()
    {
        id = 0;
        info = null;
        num = 0;
        numLabel.enabled = false;
    }
}

其中最最重要的就是接下来的类了,一个关于物品信息的类,有了它才能操控背包系统正常运作,其中文本读取的是txt的文本,其中的定义规则你可以自己定义,然后拿给策划填写就可以了,注意不要空格!!!!而且符号是英文的符号,更重要的一点是你脚本里面写的一定要和策划填写的一样!如果出现报空错误一定要仔细检查txt文本是否有误,一定要让策划仔细检查三遍!!!!!(我之前是这样写的,结果我的其它协作者使用报错了,原因是策划期间修改了文本,并且没有仔细检查,所以大家一定要注意!)

以下是完整代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;


/// <summary>
/// 一个用于管理所有Object对象信息的类
/// </summary>
public class ObjectsInfo : MonoBehaviour
{
    public static ObjectsInfo _instance;
    //使用字典的方法存储起来  默认为空
    //使用ID拿取物品
    public Dictionary<int, ObjectInfo> objectInfoDict = new Dictionary<int, ObjectInfo>();
    //可读取文本
    public TextAsset objectsInfoListText;
    void Awake()
    {
        _instance = this;
        //测试是否成功
        ReadInfo();
       
    }

    /// <summary>
    /// 写一个向外界提供物品信息的方法
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    public ObjectInfo GetObjectInfoById(int id)
    {
        ObjectInfo info = null;
        //根据ID获取信息
        objectInfoDict.TryGetValue(id, out info);
        return info;
    }

    //写一个读取的类
    void ReadInfo()
    {
        string text = objectsInfoListText.text;
        //拆分一行
        string[] strArray = text.Split('\n');
        //将每一行都拆分成一个一个的
        foreach (string str in strArray)
        {
            string[] proArray = str.Split(',');
            //new一个ObjectInfo存储物品信息
            ObjectInfo info = new ObjectInfo();
            //将文本一行内容一个一个读取,存到新new的对象里面去
            int id = int.Parse(proArray[0]);
            string name = proArray[1];
            string icon_name = proArray[2];
            string str_type = proArray[3];
            //首先定义一种类型
            ObjectType type = ObjectType.Drug;
            switch (str_type)
            {
                case "Drug":
                    type = ObjectType.Drug;
                    break;
                case "Equip":
                    type = ObjectType.Equip;
                    break;
                case "Mat":
                    type = ObjectType.Mat;
                    break;
                    //其它的物品种类就在后面添加即可
            }
            //存进去
            info.id = id; info.name = name; info.icon_name = icon_name; info.type = type;
            //药品系列赋值
            if (type == ObjectType.Drug)
            {
                int hp = int.Parse(proArray[4]);
                int mp = int.Parse(proArray[5]);
                int price_sell = int.Parse(proArray[6]);
                int price_buy = int.Parse(proArray[7]);
                //存进去
                info.hp = hp;
                info.mp = mp;
                info.price_sell = price_sell;
                info.price_buy = price_buy;
            }

            //装备系列赋值
            if(type==ObjectType.Equip)
            {
                info.attack = int.Parse(proArray[4]);
                info.def = int.Parse(proArray[5]);
                info.speed = int.Parse(proArray[6]);
                info.price_sell = int.Parse(proArray[9]);
                info.price_buy = int.Parse(proArray[10]);
                string str_dresstype = proArray[7];
                switch(str_dresstype)
                {
                    case "Headgear":
                        info.dressType = DressType.Headgear;
                        break;
                    case "Armor":
                        info.dressType = DressType.Armor;
                        break;
                    case "LeftHand":
                        info.dressType = DressType.LeftHand;
                        break;
                    case "RightHand":
                        info.dressType = DressType.RightHand;
                        break;
                    case "Shoe":
                        info.dressType = DressType.Shoe;
                        break;
                    case "Accessory":
                        info.dressType = DressType.Accessory;
                        break;
                }
                string str_apptype = proArray[8];
                switch(str_apptype)
                {
                    case "Swordman":
                        info.applicationType = ApplicationType.Swordman;
                        break;
                    case "Magician":
                        info.applicationType = ApplicationType.Magician;
                        break;
                    case "Common":
                        info.applicationType = ApplicationType.Common;
                        break;
                }
            }
            //将他们添加到字典之中
            objectInfoDict.Add(id, info);
        }
    }
}

/// <summary>
/// 用于管理物品种类的枚举
/// 建立一个枚举 方便日后更多品种的物品信息添加
/// </summary>
public enum ObjectType
{
    //药品系列
    Drug,
    Equip,
    Mat
}

/// <summary>
/// 用于处理装备的信息
/// </summary>
public enum DressType
{
    Headgear,
    Armor,
    RightHand,
    LeftHand,
    Shoe,
    Accessory
}

/// <summary>
/// 用于处理不同类型的信息
/// </summary>
public enum ApplicationType
{
    Swordman,//剑士
    Magician,//魔法师
    Common//通用
}

/// <summary>
/// 一个用于管理单个物品信息的类
/// </summary>
public class ObjectInfo
{
    public int id; //索引值
    public string name;  //物品名字
    public string icon_name;   //物品加载的图片名字(存图集的名字)
    public ObjectType type;   //物品的种类
    public int hp;            //添加的HP值
    public int mp;            //添加的MP值
    public int price_sell;    //售卖的价格
    public int price_buy;    //卖出的价格(玩家)

    public int attack;
    public int def;
    public int speed;
    public DressType dressType;
    public ApplicationType applicationType;
}

以上是背包系统的完整代码,如果你直接复制发现了报错,那可能是因为我在里面关联了其它系统,找出来修改一下就好了,或者直接问我,核心的内容就是这些,希望对你有所帮助,点个赞支持一下吧!

  • 18
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Nicole Potter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值