当前位置:   article > 正文

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

游戏背包功能的实现

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

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

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

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using static UnityEditor.Progress;
  5. /// <summary>
  6. /// 一个用于控制背包內物品的类
  7. /// </summary>
  8. public class InventoryItem : UIDragDropItem
  9. {
  10. //关联物品的图片
  11. public UISprite sprite;
  12. private int id;
  13. //关联显示窗口
  14. public UISprite tipWindow1;
  15. public UIButton tipbtnOk;
  16. public UIButton tipbtnCancel;
  17. void Update()
  18. {
  19. if (isHover)
  20. {
  21. //显示提示信息
  22. InventoryDes._instance.Show(id);
  23. if(Input.GetMouseButtonDown(1))
  24. {
  25. //按下鼠标右键开始穿戴
  26. //显示窗口
  27. tipWindow1.gameObject.SetActive(true);
  28. tipbtnOk.onClick.Add(new EventDelegate(() =>
  29. {
  30. bool success = EquipmentUI._instance.Dress(id);
  31. if(success)
  32. {
  33. transform.parent.GetComponent<InventoryItemGrid>().MinusNumber();
  34. }
  35. tipWindow1.gameObject.SetActive(false);
  36. }));
  37. tipbtnCancel.onClick.Add(new EventDelegate(() =>
  38. {
  39. tipWindow1.gameObject.SetActive(false);
  40. }));
  41. }
  42. }
  43. }
  44. protected override void OnDragDropRelease(GameObject surface)
  45. {
  46. base.OnDragDropRelease(surface);
  47. //测试
  48. if (surface != null)
  49. {
  50. if (surface.tag == Tags.inventory_item_grid)
  51. {
  52. //拖放至空格子里面
  53. if (surface == this.transform.parent.gameObject)
  54. {
  55. //拖放在自己的格子里面
  56. }
  57. else
  58. {
  59. InventoryItemGrid oldParent = this.transform.parent.GetComponent<InventoryItemGrid>();
  60. this.transform.parent = surface.transform;
  61. //zhuyi
  62. ResetPosition();
  63. InventoryItemGrid newParent = surface.GetComponent<InventoryItemGrid>();
  64. newParent.SetId(oldParent.id, oldParent.num);
  65. oldParent.ClearInfo();
  66. }
  67. }
  68. else if (surface.tag == Tags.inventory_item)
  69. {
  70. //拖放在有物品的格子里面
  71. InventoryItemGrid grid1 = this.transform.parent.GetComponent<InventoryItemGrid>();
  72. InventoryItemGrid grid2 = surface.transform.parent.GetComponent<InventoryItemGrid>();
  73. int id = grid1.id; int num = grid1.num;
  74. grid1.SetId(grid2.id, grid2.num);
  75. grid2.SetId(id, num);
  76. }
  77. else if(surface.tag==Tags.shortcut)
  78. {
  79. //拖动到快捷栏当中
  80. surface.GetComponent<ShortCutGrid>().SetInventory(id);
  81. }
  82. }
  83. else
  84. {
  85. }
  86. ResetPosition();
  87. }
  88. //重置位置
  89. void ResetPosition()
  90. {
  91. transform.localPosition = Vector3.zero;
  92. }
  93. //注意这里
  94. //public void SetId(int id)
  95. //{
  96. // ObjectInfo info=ObjectsInfo._instance.GetObjectInfoById(id);
  97. // sprite.spriteName = info.icon_name;
  98. //}
  99. public void SetIconName(int id, string icon_name)
  100. {
  101. sprite.spriteName = icon_name;
  102. this.id = id;
  103. }
  104. //public void SetIconName(string icon_name)
  105. //{
  106. // if (icon_name == null)
  107. // {
  108. // sprite.spriteName = "Icon-potion1";
  109. // Debug.Log("null");
  110. // }
  111. // else
  112. // Debug.Log("NOT NULL" + icon_name);
  113. // // sprite.spriteName = icon_name;
  114. //}
  115. private bool isHover = false;
  116. public void OnHoverOver()
  117. {
  118. isHover = true;
  119. }
  120. public void OnHoverOut()
  121. {
  122. isHover = false;
  123. }
  124. }
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. /// <summary>
  5. /// 一个用于管理背包內所有格子的类
  6. /// </summary>
  7. public class Inventory : MonoBehaviour
  8. {
  9. public static Inventory _instance;
  10. private TweenPosition tween;
  11. //定义金币的数量 初始化为1000
  12. private int coinCount = 1000;
  13. //使用List将格子们存储起来
  14. public List<InventoryItemGrid> itemGridList = new List<InventoryItemGrid>();
  15. //关联金币文本,控制数量
  16. public UILabel coinNumberLabel;
  17. public GameObject inventoryItem;
  18. //关联背包的显示和隐藏(按钮)
  19. public UIButton btnBag;
  20. public UIButton btnClose;
  21. private bool isShow=false;
  22. void Awake()
  23. {
  24. _instance = this;
  25. tween=this.GetComponent<TweenPosition>();
  26. }
  27. private void Start()
  28. {
  29. btnBag.onClick.Add(new EventDelegate(() =>
  30. {
  31. Show();
  32. }));
  33. btnClose.onClick.Add(new EventDelegate(() =>
  34. {
  35. Hide();
  36. }));
  37. }
  38. public void Show()
  39. {
  40. isShow=true;
  41. tween.PlayForward();
  42. }
  43. public void Hide()
  44. {
  45. isShow=false;
  46. tween.PlayReverse();
  47. }
  48. public void TransformState()
  49. {
  50. if(isShow==false)
  51. {
  52. Show();
  53. }
  54. else
  55. {
  56. Hide();
  57. }
  58. }
  59. //增加金币的方法
  60. public void AddCoin(int count)
  61. {
  62. coinCount += count;
  63. coinNumberLabel.text = coinCount.ToString();//更新金币的显示
  64. }
  65. //取款方法
  66. public bool GetCoin(int count)
  67. {
  68. if(coinCount>=count)
  69. {
  70. coinCount-=count;
  71. coinNumberLabel.text = coinCount.ToString();//更新金币显示
  72. return true;
  73. }
  74. return false;
  75. }
  76. //测试背包系统的方法
  77. void Update()
  78. {
  79. if (Input.GetKeyDown(KeyCode.X))
  80. {
  81. GetId(Random.Range(2001,2023));
  82. }
  83. }
  84. //拾取到物品 添加到物品栏里面
  85. //处理拾取物品的功能
  86. public void GetId(int id,int count=1)
  87. {
  88. //查找所有物品中是否存在该物品
  89. //存在就数量+1
  90. InventoryItemGrid grid = null;
  91. foreach (InventoryItemGrid temp in itemGridList)
  92. {
  93. if (temp.id == id)
  94. {
  95. grid = temp;
  96. break;
  97. }
  98. }
  99. if (grid != null)
  100. {
  101. grid.PlusNumber(count);
  102. }
  103. else
  104. {
  105. //不存在的情况
  106. foreach (InventoryItemGrid temp in itemGridList)
  107. {
  108. if (temp.id == 0)
  109. {
  110. grid = temp;
  111. break;
  112. }
  113. }
  114. //不存在就放在空的格子里面
  115. if (grid != null)
  116. {
  117. GameObject itemGo = NGUITools.AddChild(grid.gameObject, inventoryItem);
  118. itemGo.transform.localPosition = Vector3.zero;
  119. itemGo.GetComponent<UISprite>().depth = 4;
  120. grid.SetId(id,count);
  121. }
  122. }
  123. }
  124. public bool MinusId(int id,int count=1)
  125. {
  126. InventoryItemGrid grid=null;
  127. foreach(InventoryItemGrid temp in itemGridList)
  128. {
  129. if (temp.id == id)
  130. {
  131. grid = temp;
  132. break;
  133. }
  134. }
  135. if (grid == null)
  136. {
  137. return false;
  138. }
  139. else
  140. {
  141. bool isSuccess = grid.MinusNumber(count);
  142. return isSuccess;
  143. }
  144. }
  145. }

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

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. /// <summary>
  5. /// 一个用于控制物品信息显示的类
  6. /// </summary>
  7. public class InventoryDes : MonoBehaviour
  8. {
  9. public static InventoryDes _instance;
  10. public UILabel label;
  11. //计时器
  12. private float timer = 0;
  13. void Awake()
  14. {
  15. _instance = this;
  16. this.gameObject.SetActive(false);
  17. }
  18. void Update()
  19. {
  20. if (this.gameObject.activeInHierarchy == true)
  21. {
  22. timer -= Time.deltaTime;
  23. if (timer <= 0)
  24. {
  25. this.gameObject.SetActive(false);
  26. }
  27. }
  28. }
  29. //显示的方法
  30. public void Show(int id)
  31. {
  32. this.gameObject.SetActive(true);
  33. timer = 0.1f;
  34. transform.position = UICamera.currentCamera.ScreenToWorldPoint(Input.mousePosition);
  35. ObjectInfo info = ObjectsInfo._instance.GetObjectInfoById(id);
  36. string des = "";
  37. switch (info.type)
  38. {
  39. case ObjectType.Drug:
  40. des = GetDrugDes(info);
  41. break;
  42. case ObjectType.Equip:
  43. des = GetEquipDes(info);
  44. break;
  45. }
  46. //更新显示
  47. label.text = des;
  48. }
  49. string GetDrugDes(ObjectInfo info)
  50. {
  51. string str = "";
  52. str +="名称:" + info.name + "\n";
  53. str += "+HP:" + info.hp + "\n";
  54. str += "+MP:" + info.mp + "\n";
  55. str += "出售价:" + info.price_sell + "\n";
  56. str += "购买价:" + info.price_buy;
  57. return str;
  58. }
  59. string GetEquipDes(ObjectInfo info)
  60. {
  61. string str = "";
  62. str += "名称" + info.name + "\n";
  63. switch(info.dressType)
  64. {
  65. case DressType.Headgear:
  66. str += "穿戴类型:头盔\n";
  67. break;
  68. case DressType.Armor:
  69. str += "穿戴类型:盔甲\n";
  70. break;
  71. case DressType.LeftHand:
  72. str += "穿戴类型:左手\n";
  73. break;
  74. case DressType.RightHand:
  75. str += "穿戴类型:右手\n";
  76. break;
  77. case DressType.Shoe:
  78. str += "穿戴类型:鞋\n";
  79. break;
  80. case DressType.Accessory:
  81. str += "穿戴类型:饰品\n";
  82. break;
  83. }
  84. switch(info.applicationType)
  85. {
  86. case ApplicationType.Swordman:
  87. str += "适用类型:剑士\n";
  88. break;
  89. case ApplicationType.Magician:
  90. str += "适用类型:魔法师\n";
  91. break;
  92. case ApplicationType.Common:
  93. str += "适用类型:通用\n";
  94. break;
  95. }
  96. str += "伤害值:" + info.attack + "\n";
  97. str += "防御值:" + info.def + "\n";
  98. str += "速度值:" + info.speed + "\n";
  99. return str;
  100. }
  101. }

格子的逻辑:
 

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. /// <summary>
  5. /// 一个用于控制背包单个格子的类
  6. /// </summary>
  7. public class InventoryItemGrid : MonoBehaviour
  8. {
  9. public static InventoryItemGrid _instance;
  10. public int id = 0;
  11. private ObjectInfo info = null;
  12. public int num = 0;
  13. public UILabel numLabel;
  14. void Awake()
  15. {
  16. _instance = this;
  17. //一开始隐藏文本
  18. numLabel.enabled= false;
  19. }
  20. public void SetId(int id, int num = 1)
  21. {
  22. this.id = id;
  23. info = ObjectsInfo._instance.GetObjectInfoById(id);
  24. InventoryItem item = this.GetComponentInChildren<InventoryItem>();
  25. item.SetIconName(id, info.icon_name);
  26. numLabel.enabled = true;
  27. this.num = num;
  28. numLabel.text = num.ToString();
  29. }
  30. public void PlusNumber(int num = 1)
  31. {
  32. this.num += num;
  33. //更新显示
  34. numLabel.text = this.num.ToString();
  35. }
  36. //用于减去数量的 表示装备是否减去成功
  37. public bool MinusNumber(int num=1)
  38. {
  39. if(this.num>=num)
  40. {
  41. this.num -= num;
  42. numLabel.text = this.num.ToString();
  43. if(this.num==0)
  44. {
  45. //清空物品
  46. ClearInfo();
  47. GameObject.Destroy(this.GetComponentInChildren<InventoryItem>().gameObject);
  48. }
  49. return true;
  50. }
  51. return false;
  52. }
  53. //public void PlusNumber(int num = 1)
  54. //{
  55. // if (this.num < 10)
  56. // {
  57. // this.num = num + this.num;
  58. // //更新显示
  59. // numLabel.text = this.num.ToString();
  60. // if (this.num <= 1)
  61. // numLabel.enabled = false;
  62. // else
  63. // numLabel.enabled = true;
  64. // }
  65. //}
  66. //设置一个清空的方法
  67. public void ClearInfo()
  68. {
  69. id = 0;
  70. info = null;
  71. num = 0;
  72. numLabel.enabled = false;
  73. }
  74. }

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

以下是完整代码:

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. /// <summary>
  5. /// 一个用于管理所有Object对象信息的类
  6. /// </summary>
  7. public class ObjectsInfo : MonoBehaviour
  8. {
  9. public static ObjectsInfo _instance;
  10. //使用字典的方法存储起来 默认为空
  11. //使用ID拿取物品
  12. public Dictionary<int, ObjectInfo> objectInfoDict = new Dictionary<int, ObjectInfo>();
  13. //可读取文本
  14. public TextAsset objectsInfoListText;
  15. void Awake()
  16. {
  17. _instance = this;
  18. //测试是否成功
  19. ReadInfo();
  20. }
  21. /// <summary>
  22. /// 写一个向外界提供物品信息的方法
  23. /// </summary>
  24. /// <param name="id"></param>
  25. /// <returns></returns>
  26. public ObjectInfo GetObjectInfoById(int id)
  27. {
  28. ObjectInfo info = null;
  29. //根据ID获取信息
  30. objectInfoDict.TryGetValue(id, out info);
  31. return info;
  32. }
  33. //写一个读取的类
  34. void ReadInfo()
  35. {
  36. string text = objectsInfoListText.text;
  37. //拆分一行
  38. string[] strArray = text.Split('\n');
  39. //将每一行都拆分成一个一个的
  40. foreach (string str in strArray)
  41. {
  42. string[] proArray = str.Split(',');
  43. //new一个ObjectInfo存储物品信息
  44. ObjectInfo info = new ObjectInfo();
  45. //将文本一行内容一个一个读取,存到新new的对象里面去
  46. int id = int.Parse(proArray[0]);
  47. string name = proArray[1];
  48. string icon_name = proArray[2];
  49. string str_type = proArray[3];
  50. //首先定义一种类型
  51. ObjectType type = ObjectType.Drug;
  52. switch (str_type)
  53. {
  54. case "Drug":
  55. type = ObjectType.Drug;
  56. break;
  57. case "Equip":
  58. type = ObjectType.Equip;
  59. break;
  60. case "Mat":
  61. type = ObjectType.Mat;
  62. break;
  63. //其它的物品种类就在后面添加即可
  64. }
  65. //存进去
  66. info.id = id; info.name = name; info.icon_name = icon_name; info.type = type;
  67. //药品系列赋值
  68. if (type == ObjectType.Drug)
  69. {
  70. int hp = int.Parse(proArray[4]);
  71. int mp = int.Parse(proArray[5]);
  72. int price_sell = int.Parse(proArray[6]);
  73. int price_buy = int.Parse(proArray[7]);
  74. //存进去
  75. info.hp = hp;
  76. info.mp = mp;
  77. info.price_sell = price_sell;
  78. info.price_buy = price_buy;
  79. }
  80. //装备系列赋值
  81. if(type==ObjectType.Equip)
  82. {
  83. info.attack = int.Parse(proArray[4]);
  84. info.def = int.Parse(proArray[5]);
  85. info.speed = int.Parse(proArray[6]);
  86. info.price_sell = int.Parse(proArray[9]);
  87. info.price_buy = int.Parse(proArray[10]);
  88. string str_dresstype = proArray[7];
  89. switch(str_dresstype)
  90. {
  91. case "Headgear":
  92. info.dressType = DressType.Headgear;
  93. break;
  94. case "Armor":
  95. info.dressType = DressType.Armor;
  96. break;
  97. case "LeftHand":
  98. info.dressType = DressType.LeftHand;
  99. break;
  100. case "RightHand":
  101. info.dressType = DressType.RightHand;
  102. break;
  103. case "Shoe":
  104. info.dressType = DressType.Shoe;
  105. break;
  106. case "Accessory":
  107. info.dressType = DressType.Accessory;
  108. break;
  109. }
  110. string str_apptype = proArray[8];
  111. switch(str_apptype)
  112. {
  113. case "Swordman":
  114. info.applicationType = ApplicationType.Swordman;
  115. break;
  116. case "Magician":
  117. info.applicationType = ApplicationType.Magician;
  118. break;
  119. case "Common":
  120. info.applicationType = ApplicationType.Common;
  121. break;
  122. }
  123. }
  124. //将他们添加到字典之中
  125. objectInfoDict.Add(id, info);
  126. }
  127. }
  128. }
  129. /// <summary>
  130. /// 用于管理物品种类的枚举
  131. /// 建立一个枚举 方便日后更多品种的物品信息添加
  132. /// </summary>
  133. public enum ObjectType
  134. {
  135. //药品系列
  136. Drug,
  137. Equip,
  138. Mat
  139. }
  140. /// <summary>
  141. /// 用于处理装备的信息
  142. /// </summary>
  143. public enum DressType
  144. {
  145. Headgear,
  146. Armor,
  147. RightHand,
  148. LeftHand,
  149. Shoe,
  150. Accessory
  151. }
  152. /// <summary>
  153. /// 用于处理不同类型的信息
  154. /// </summary>
  155. public enum ApplicationType
  156. {
  157. Swordman,//剑士
  158. Magician,//魔法师
  159. Common//通用
  160. }
  161. /// <summary>
  162. /// 一个用于管理单个物品信息的类
  163. /// </summary>
  164. public class ObjectInfo
  165. {
  166. public int id; //索引值
  167. public string name; //物品名字
  168. public string icon_name; //物品加载的图片名字(存图集的名字)
  169. public ObjectType type; //物品的种类
  170. public int hp; //添加的HP值
  171. public int mp; //添加的MP值
  172. public int price_sell; //售卖的价格
  173. public int price_buy; //卖出的价格(玩家)
  174. public int attack;
  175. public int def;
  176. public int speed;
  177. public DressType dressType;
  178. public ApplicationType applicationType;
  179. }

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/136027?site
推荐阅读
相关标签
  

闽ICP备14008679号