4.1 道具系统补全:合成系统 & UI 前言
【爆甲英雄传】4.背包系统
本篇原本属于UI的,但是作为一个负责任的茶水,在回顾之前的帖子的时候,发现漏了一个很重要的功能,就是合成系统,我们在设计道具的时候,已经设计好了配方这个类型的道具,但是,在背包系统中却没有合成的功能,这样可不行啊,合成是一个游戏的精髓啊,所以,确定本篇乱入,补全道具系统的核心代码,当让,最后附上测试单元,这样就可以测试合成这一块了,具体的新UI demo(含合成功能),将会随下篇一起附上。
好了,这次其实不用什么新建什么脚本了,我们只要修改之前的就可以了。 照旧,最后附上全部代码。
Inventory_Manager 里添加新的函数
public int Get_Amount_Item(int itemID, Inventory_Type type), 返回道具的数量,用于判断是否有足够的材料制作新道具,若道具不熏在,返回-1。道具ID,背包类型。
public bool Has_Item(int itemID, Inventory_Type type),是否拥有指定道具,简单不解释。道具ID,背包类型。
public bool Can_Create_Item(int recipeID, Inventory_Type type),判断是否能制作新的道具,主要判定是否有足够材料。配方的道具ID,背包类型。
public Item_Profile Create_Item(int recipeID, Inventory_Type type),制作道具,返回道具的描述文件(脚本或类型),并移除材料,配方保留。配方的道具ID,背包类型。(注意,正常的合成系统应该只能在玩家的背包或仓库才能进行的,所以外部调用的时候,需要判断好背包类型的合法性。UI篇里会继续探讨。)
Unit_Inventory_Manager 和 Unit_Inventory_Manager_Editor 只是添加了一个提供测试函数而已,没什么也别。但是值得注意的是,Unit_Inventory_Manager 中的参数 itemInfo 返回一个新制作出来的道具,用于快速定位而已,可无视。
复制到好新的代码,然后设计好你的配方,保证你的背包有足够的材料,然后。。。合成吧。
好了,到目前位置,字数不够,没有贴图,这样发文肯定会被打的,怎么办的,一个字,磨!磨多点字出来呗,那茶水就趁这个时间给大家预热下UI篇吧。
================咸湿分割线================
UI 前言
首先,下载好NGUI,最新不最新到不重要,重要的是不要太旧。然后茶水假设大家都有一定程度的NGUI的开发经验,如果你是第一次使用NGUI,可以看看其他蛮牛大神的帖子。
然后,上图:
是不是吓死人呢,哈哈,不要怕,茶水也是这么过来的。首先,我们来一步步的分解他的结构,
NGUI的一些基本元素,例如UI Camera,UI Root这些就不用多说了,我们主要集中在System Buttons和后面6个UI xXXX的蓝色字就好了。
这6个元素在层级机构中都属于同一级,我们点击其中一个来看看他的组件成员。
如图所示,我们看到的是System Buttons这一块,他所包含的是一个UIPanel,所以我们这个层级的元素全都是UIPanel,这样组织绝对只是NGUI的结构所限,NGUI提供了一个很好的层级间相互叠加的一个管理,用UIPanel的目的就是方便实现次管理,简单说,就是面板间的前后遮挡问题,2D中最常见的问题。好了,这里不用深究这个问题,这不是我们的重点,我只是在磨字数而已。
[size=13.63636302948px]================咸湿分割线================
现在开始讲解各个各个面板的功能。
System Buttons,就是一个基本界面,目的提供一些常用的界面操作,返回主菜单,或且开关某个指定的面板,直接提供一组系统级的按钮,这里我们看到他下挂了一个Windows Reset对象,它是一个按钮,重置所以面板,方便测试而已。
UI Itembase review windows, 这个面板用于查看我们的道具系统中的道具数据库,主要用于测试而已,提供一种可视化的方式去检测我们设计好的道具,实际游戏中这个面板并不需要。大家看到它的层级结构,是不是很吓人呢,其实很多都是NGUI中的布局元素,主要的在Panel下的元素,这些后篇会详细说明。
UI Store Inventory windows,仓库面板,不解释。
UI Player Inventory windows, UI Shop Inventory windows,玩家背包面板和商店面板,不解释too。
UI Description windows,描述面板,就是道具的描述,当你点击某个道具的时候,这个面板就是显示玩家所选择的道具一些详情。我们可以看到它下挂了各种UI Description X,根据玩家所选择的道具,切换不用的面板用于显示不用的类型的道具,如果你新增了新的道具类型,这里也需要新增一个与之对应的面板用于显示。然后,懒的话也可以设计一个通用的面板,最简单的就是很多手机或掌机最常用的办法,就是设计一个仅有一个text box的面板,是不是很通用呢。哈哈。
OK,基本的层级结构终于讲完了,理论的东西总是这个鼓噪无味,希望大家没有睡着了,不知道大家有没有留意到,这里有个元素经常出现在各大面板中,没错,它就是 Item Slot X,这个就是传说中的道具格或道具槽,这个东西是道具UI中最重要的组成部分,也是最小的一个单元,我们先来偷窥下它的结构,
别怕,众多组件都是NGUI自带的,我们需要做的就是编写一个UI_Item_Slot而已,而且还是用你们最喜爱的C#,是不是很简单呢。Item Slot主要提供一个显示道具图标,名称,数量和基本的拖放操作。
投票部分:
由于UI的设计不是一般的痛苦,由于UI中的代码都是环环紧扣,交叉性比较大,所以一篇下来,给出的代码可能还不能用,因为需要后篇的别的代码的支持,所以茶水在此想发起一个投票,看看大家的意愿,大家回帖表达意愿就好了,貌似不能发起投票。
1.先全部设计好UI元素再设计代码。(默认) 2.边设计UI元素边设计代码。 3.都行。
- Inventory_Manager
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- [System.Serializable]
- public class Inventory_Manager : MonoBehaviour {
- public int money;
- List<Inventory_Slot> current_inventory;
- int current_limit;
- public List<Inventory_Slot> player_inventory;
- int player_inventory_limit = 40;
- public List<Inventory_Slot> store_inventory;
- int store_inventory_limit = 99999; // infinite almost
- public List<Inventory_Slot> shop_inventory;
- int shop_inventory_limit = 99999; // infinite almost
- static Inventory_Manager im;
- #region Equipment
- public int
- equipmentID_Main_Weapon = -1,
- equipmentID_Second_Weapon = -1,
- equipmentID_Shield = -1,
- equipmentID_Head = -1,
- equipmentID_Shoulder = -1,
- equipmentID_Belt = -1;
- // add more equipment here ...
- #endregion
- public enum Inventory_Type
- {
- Player,
- Store,
- Shop,
- None
- };
- // Use this for initialization
- void Awake ()
- {
- DontDestroyOnLoad(gameObject);
- im = gameObject.GetComponent<Inventory_Manager>();
- }
- public static Inventory_Manager Get_Manager()
- {
- if (im == null)
- {
- Global_Manager.InitAll();
- }
- return im;
- }
- void Select_Inventory(Inventory_Type type)
- {
- switch (type)
- {
- case Inventory_Type.Player:
- current_inventory = player_inventory;
- current_limit = player_inventory_limit;
- break;
- case Inventory_Type.Store:
- current_inventory = store_inventory;
- current_limit = store_inventory_limit;
- break;
- case Inventory_Type.Shop:
- current_inventory = shop_inventory;
- current_limit = shop_inventory_limit;
- break;
- default:
- current_inventory = null;
- current_limit = 0;
- break;
- }
- }
- public bool Deposit(int itemID, Inventory_Type type)
- {
- Select_Inventory(type);
- if (null == current_inventory)
- return false;
- Inventory_Slot slot = Current_Slot(itemID,true);
- if (slot !=null)
- {
- if (slot.Deposit())
- {
- return true;
- }
- else
- {
- // add a new stack
- return Add_New_Slot(itemID);
- }
- }
- else
- {
- // add a new stack
- return Add_New_Slot(itemID);
- }
- return false;
- }
- public bool Withdraw(int itemID, Inventory_Type type)
- {
- Select_Inventory(type);
- if (null == current_inventory)
- return false;
- Inventory_Slot slot = Current_Slot(itemID,false);
- if (slot != null)
- {
- if (slot.Withdraw())
- {
- current_inventory.Remove(slot);
- }
- return true;
- }
- return false;
- }
- public bool Withdraw_at_slot(int slotID, Inventory_Type type)
- {
- Select_Inventory(type);
- if (null == current_inventory)
- return false;
- Inventory_Slot slot = current_inventory[slotID];
-
- if (slot != null)
- {
-
- if (slot.Withdraw())
- {
- current_inventory.Remove(slot);
- }
-
- return true;
- }
-
- return false;
- }
- public int Get_Current_Stack(int slotID, Inventory_Type type)
- {
- Select_Inventory(type);
- if (null == current_inventory)
- return -1;
- return current_inventory[slotID].current_stack;
- }
- Inventory_Slot Current_Slot(int itemID, bool deposit)
- {
- if (deposit)
- {
- foreach(Inventory_Slot slot in current_inventory)
- {
- if (slot.item_id == itemID)
- {
- if (!slot.Full_Stack())
- return slot;
- }
- }
- }
- else
- {
- for (int i=current_inventory.Count-1; i>=0; i--)
- {
- Inventory_Slot slot = current_inventory;
- if (slot.item_id == itemID)
- {
- return slot;
- }
- }
- }
-
- return null;
- }
- bool Add_New_Slot(int itemID)
- {
- // add a new stack
- if (current_inventory.Count < current_limit)
- {
- Inventory_Slot newSlot = new Inventory_Slot(itemID);
- current_inventory.Add(newSlot);
- return true;
- }
- return false;
- }
- public void Sort(Inventory_Type type)
- {
- Select_Inventory(type);
- if (null == current_inventory)
- return;
- current_inventory.Sort();
- }
- // get the item's amount in inventory
- public int Get_Amount_Item(int itemID, Inventory_Type type)
- {
- Select_Inventory(type);
- if (null == current_inventory)
- return -1;
- int item_count = 0;
- for (int i=0; i<current_inventory.Count; i++)
- {
- Inventory_Slot slot = current_inventory;
- if (slot.item_id == itemID)
- {
- item_count += slot.current_stack;
- }
- }
- return item_count;
- }
- // has the item
- public bool Has_Item(int itemID, Inventory_Type type)
- {
- Select_Inventory(type);
- if (null == current_inventory)
- return false;
- for (int i=0; i<current_inventory.Count; i++)
- {
- Inventory_Slot slot = current_inventory;
- if (slot.item_id == itemID)
- {
- return true;
- }
- }
- return false;
- }
- // check if can create a item
- public bool Can_Create_Item(int recipeID, Inventory_Type type)
- {
- Item_Profile recipe = Item_Database_Manager.Get_Manager().Get_Item(recipeID);
- // this item must be a recipe, otherwise, return
- if (recipe.type != Item_Profile.TYPE.Recipe)
- return false;
-
- // check own this recipe, if not, return
- Select_Inventory(type);
- if (null == current_inventory)
- return false;
- if (!Has_Item(recipeID, type))
- return false;
-
- // check what material should be needed, if not enough, return
- int material_count = recipe.parts.Length;
- for (int i=0; i<material_count;i++)
- {
- Item_Profile.Recipe_Parts recipe_part = recipe.parts;
- Item_Profile part = recipe_part.part;
- if (!Has_Item(part.item_id, type))
- return false;
- if (Get_Amount_Item(part.item_id, type) < recipe_part.number)
- return false;
-
- }
- return true;
- }
- // create a item base on the recipe.
- public Item_Profile Create_Item(int recipeID, Inventory_Type type)
- {
- // check if can create a item.
- if (!Can_Create_Item(recipeID,type))
- return null;
- Item_Profile recipe = Item_Database_Manager.Get_Manager().Get_Item(recipeID);
- // do the create process
- if (!Inventory_Manager.Get_Manager().Deposit(recipe.final_product.item_id, type))
- return null;
- // withdraw the parts
- int material_count = recipe.parts.Length;
- for (int i=0; i<material_count;i++)
- {
- Item_Profile.Recipe_Parts recipe_part = recipe.parts;
- Item_Profile part = recipe_part.part;
- for (int k=0; k<recipe_part.number ;k++)
- {
- Inventory_Manager.Get_Manager().Withdraw(part.item_id, type);
- }
- }
- // return the item profile
- return Item_Database_Manager.Get_Manager().Get_Item(recipe.final_product.item_id);
- }
- }
- Unit_Inventory_Manager
- [C#] 纯文本查看 复制代码
- using UnityEngine;
- using System.Collections;
- public class Unit_Inventory_Manager : MonoBehaviour {
- public int itemID; // which item use to test
- public Inventory_Manager.Inventory_Type inventory_type;
- public Item_Profile itemInfo;
- public void Deposit()
- {
- Inventory_Manager.Get_Manager().Deposit(itemID,inventory_type);
- }
- public void Withdraw()
- {
- Inventory_Manager.Get_Manager().Withdraw(itemID, inventory_type);
- }
- public void Show_Info()
- {
- Item_Profile item = Item_Database_Manager.Get_Manager().Get_Item(itemID);
- itemInfo = item;
- }
- // create a item base on the recipe [move it to the inventory manager]
- public void Create_Item()
- {
- itemInfo = Inventory_Manager.Get_Manager().Create_Item(itemID, inventory_type);
- if (itemInfo == null)
- {
- Debug.Log("Item create failed!");
- }
- else
- {
- Debug.Log("Item create successful!");
- }
- }
- }
- Unit_Inventory_Manager_Editor
- [C#] 纯文本查看 复制代码
- using UnityEngine;
- using System.Collections;
- using UnityEditor;
- [CustomEditor(typeof(Unit_Inventory_Manager))]
- public class Unit_Inventory_Manager_Editor : Editor
- {
- public override void OnInspectorGUI ()
- {
- Unit_Inventory_Manager manager = target as Unit_Inventory_Manager;
- //serializedObject.Update();
- DrawDefaultInspector();
- //manager.itemID = EditorGUILayout.IntField("item id", manager.itemID);
- //EditorGUILayout.PropertyField(serializedObject.FindProperty("inventory_type"),true);
- if(GUILayout.Button("Unit Info"))
- {
- manager.Show_Info();
- }
- if(GUILayout.Button("Unit Deposit"))
- {
- manager.Deposit();
- }
- if(GUILayout.Button("Unit Withdraw"))
- {
- manager.Withdraw();
- }
- if(GUILayout.Button("Create Item"))
- {
- manager.Create_Item();
- }
- //EditorGUILayout.PropertyField(serializedObject.FindProperty("itemInfo"),true);
- serializedObject.ApplyModifiedProperties();
- }
- }
复制代码
|