基于Unity3D(UGUI)的背包系统<三>

来源:互联网 发布:牛扒和牛排区别知乎 编辑:程序博客网 时间:2024/05/01 23:46

这一篇,主要讲解UI逻辑处理方面,以及UI和该篇中的数据两者之间的使用。

首先补充一个上篇中缺少的一个配方类:这个类主要是用来保存锻造的所需的材料及锻造出来的结果。

using UnityEngine;using System.Collections;using System.Collections.Generic;/// <summary>/// 配方类:用来保存锻造的所需的材料及锻造出来的结果/// </summary>public class Formula{    public int Item1ID { get; private  set; }//用来锻造的物品1的ID    public int Item1Amount { get; private set; }//用来锻造的物品1的数量    public int Item2ID { get; private set; }//用来锻造的物品2的ID    public int Item2Amount { get; private set; }//用来锻造的物品2的数量    public int ResID { get; set; }//保存锻造结果的ID    private List<int> needIDList = new List<int>();//保存锻造所需要材料的ID(相当于锻造的配方)    public List<int> NeedIDList { get { return needIDList; } }    public Formula(int item1ID, int item1Amount, int item2ID, int item2Amount, int resID )    {        this.Item1ID = item1ID;        this.Item1Amount = item1Amount;        this.Item2ID = item2ID;        this.Item2Amount = item2Amount;        this.ResID = resID;        //初始化配方ID        for (int i = 0; i < Item1Amount; i++)        {            needIDList.Add(Item1ID);        }        for (int i = 0; i < Item2Amount; i++)        {            needIDList.Add(Item2ID);        }    }    /// <summary>    /// 匹配所提供的物品是否 包含 锻造所需要的物品(利用ID匹配)    /// </summary>    /// <returns></returns>    public bool Match( List<int> idList )     {        List<int> tempIDList = new List<int>(idList);//临时保存函数参数数据(所拥有的物品ID),防止下面Remove代码移除时被修改        foreach (int id in needIDList)        {            bool isSuccess = tempIDList.Remove(id);            if (isSuccess == false)            {                return false;//拥有的物品和锻造所需的物品匹配失败            }        }        return true;//物品匹配成功    }}

接着,重点部分就来了。正如第一部分图中那样。总的有5个面板:背包面板,箱子面板,角色面板,商店小贩面板,以及锻造面板。其中,每一个面板都有一个基类(Inventory类),因为这些面板中有一些相似的功能和方法,所以选择使用了继承。各自对应的代码如下:

①基类Inventory:

using UnityEngine;using System.Collections;using System.Collections.Generic;using System.Text;/// <summary>///存货类, 背包和箱子的基类/// </summary>public class Inventroy : MonoBehaviour {    protected Slot[] slotArray;//存放物品槽的数组    //控制背包的显示和隐藏相关变量    private float targetAlpha = 1f;//显示目标值    private float smothing = 4f;//渐变平滑速度    private CanvasGroup canvasGroupMy;    public CanvasGroup CanvasGroupMy      //对CanvasGroup的引用,用于制作隐藏显示效果    {        get        {            if (canvasGroupMy == null)            {                canvasGroupMy = GetComponent<CanvasGroup>();            }            return canvasGroupMy;        }    }    // Use this for initialization    public virtual void Start () {//声明为虚函数,方便子类重写        slotArray = GetComponentsInChildren<Slot>();         if (canvasGroupMy == null)            {                canvasGroupMy = GetComponent<CanvasGroup>();            }    }    void Update()     {        if (this.CanvasGroupMy.alpha != targetAlpha)        {            this.CanvasGroupMy.alpha = Mathf.Lerp(this.CanvasGroupMy.alpha, targetAlpha, smothing * Time.deltaTime);            if (Mathf.Abs(this.CanvasGroupMy.alpha - targetAlpha)<.01f)            {                this.CanvasGroupMy.alpha = targetAlpha;            }        }    }    //根据Id存储物品    public bool StoreItem(int id)     {       Item item = InventroyManager.Instance.GetItemById(id);       return StoreItem(item);    }    //根据Item存储物品(重点)    public bool StoreItem(Item item)     {        if (item.ID == 0)        {            Debug.LogWarning("要存储物品的ID不存在");            return false;        }        if (item.Capacity == 1)//如果此物品只能放一个,那就找一个空的物品槽来存放即可        {           Slot slot = FindEmptySlot();           if (slot == null)//如果空的物品槽没有了           {               Debug.LogWarning("没有空的物品槽可供使用");               return false;//存储失败           }           else     //空的物品槽还有,那就把物品添加进去           {               slot.StoreItem(item);           }        }        else//如果此物品能放多个        {            Slot slot = FindSameIDSlot(item);            if (slot != null)//找到了符合条件的物品槽,那就把物品存起来            {                slot.StoreItem(item);            }            else //没有找到符合条件的物品槽,那就找一个没有存放物品的物品槽去存放物品            {                Slot emptySlot = FindEmptySlot();                if (emptySlot != null)                {                    emptySlot.StoreItem(item);//空的物品槽去存放物品                }                else // 如果连空的物品槽,也就是没有存储物品的物品槽都找不到                {                    Debug.LogWarning("没有空的物品槽可供使用");                    return false;//存储失败                }            }        }        return true; //存储成功    }    //寻找空的物品槽    private Slot FindEmptySlot()     {        foreach (Slot slot  in slotArray)        {            if (slot.transform.childCount == 0)//物品槽下面无子类,说明该物品槽为空,返回它即可            {                return slot;            }        }        return null;    }    //查找存放的物品是相同的物品槽    private Slot FindSameIDSlot(Item item)    {        foreach (Slot slot in slotArray)        {            //如果当前的物品槽已经有物品了,并且里面的物品的类型和需要找的类型一样,并且物品槽还没有被填满            if (slot.transform.childCount >= 1 && item.ID == slot.GetItemID() && slot.isFiled() == false)            {                return slot;            }        }        return null;    }    //面板的显示方法    public void Show()     {        this.CanvasGroupMy.blocksRaycasts = true;//面板显示时为可交互状态        this.targetAlpha = 1;    }    //面板的隐藏方法    public void Hide()     {        this.CanvasGroupMy.blocksRaycasts = false;//面板隐藏后为不可交互状态        this.targetAlpha = 0;    }    //控制面板的显示及隐藏关系    public void DisplaySwitch()     {        if (this.CanvasGroupMy.alpha == 0)        {            Show();        }        if (this.CanvasGroupMy.alpha == 1)        {            Hide();        }    }    //控制物品信息的保存(ID,Amount数量)    public void SaveInventory()     {        StringBuilder sb = new StringBuilder();//用来保存物品信息的字符串        foreach (Slot slot in slotArray)        {            if (slot.transform.childCount > 0 )            {                ItemUI  itemUI = slot.transform.GetChild(0).GetComponent<ItemUI>();                sb.Append(itemUI.Item.ID + "," + itemUI.Amount + "-");//用逗号分隔一个物品中的ID和数量,用 - 分隔多个物品            }            else            {                sb.Append("0-");//如果物品槽里没有物品就是0            }        }        PlayerPrefs.SetString(this.gameObject.name, sb.ToString());//保存字符串数据    }    //控制物品信息的加载(根据ID,Amount数量)    public void LoadInventory()     {        if (PlayerPrefs.HasKey(this.gameObject.name) == false) return;//判断保存的这个关键码Key是否存在,不存在就不做处理        string str = PlayerPrefs.GetString(this.gameObject.name);//获取上面保存的字符串数据        string[] itemArray = str.Split('-');//按照  -  分隔多个物品        for (int i = 0; i < itemArray.Length-1; i++)//长度减1是因为最后一个字符是 “-”,不需要取它        {            string itemStr = itemArray[i];            if (itemStr != "0")            {                string[] temp = itemStr.Split(',');//按照逗号分隔这个物品的信息(ID和Amoun数量)                int id = int.Parse(temp[0]);                Item item = InventroyManager.Instance.GetItemById(id);//通过物品ID得到该物品                int amount = int.Parse(temp[1]);                for (int j = 0; j < amount; j++)//执行Amount次StoreItem方法,一个一个的存                {                    slotArray[i].StoreItem(item);                }            }        }    }}

②背包面板:
using UnityEngine;
using System.Collections;
///
/// 背包类,继承自 存货类Inventroy
///
public class Knapscak : Inventroy {
//单例模式
private static Knapscak _instance;
public static Knapscak Instance {
get {
if (_instance == null)
{
_instance = GameObject.Find(“KnapscakPanel”).GetComponent();
}
return _instance;
}
}
}

③箱子面板

using UnityEngine;using System.Collections;/// <summary>/// 箱子类,继承自 存货类Inventroy/// </summary>public class Chest : Inventroy {    //单例模式    private static Chest _instance;    public static Chest Instance    {        get        {            if (_instance == null)            {                _instance = GameObject.Find("ChestPanel").GetComponent<Chest>();            }            return _instance;        }    }}

④角色面板

using UnityEngine;using System.Collections;using UnityEngine.UI;/// <summary>/// 角色面板类,控制角色面板的逻辑/// </summary>public class CharacterPanel : Inventroy{    //单例模式    private static CharacterPanel _instance;    public static CharacterPanel Instance     {        get         {            if (_instance == null)            {                _instance = GameObject.Find("CharacterPanel").GetComponent<CharacterPanel>();            }            return _instance;        }    }    private Text characterPropertyText;//对角色属性面板中Text组件的引用    private Player player;//对角色脚本的引用    public override void Start()    {        base.Start();        characterPropertyText = transform.Find("CharacterPropertyPanel/Text").GetComponent<Text>();        player = GameObject.FindWithTag("Player").GetComponent<Player>();        UpdatePropertyText();//初始化显示角色属性值    }    //更新角色属性显示    private void UpdatePropertyText()     {        int strength = 0, intellect = 0, agility = 0, stamina = 0, damage = 0;        foreach (EquipmentSlot slot in slotArray)//遍历角色面板中的装备物品槽        {            if (slot.transform.childCount > 0)//找到有物品的物品槽,获取里面装备的属性值            {                Item item = slot.transform.GetChild(0).GetComponent<ItemUI>().Item;                if (item is Equipment)//如果物品是装备,那就加角色对应的属性                {                    Equipment e = (Equipment)item;                    strength += e.Strength;                    intellect += e.Intellect;                    agility += e.Agility;                    stamina += e.Stamina;                }                else if (item is Weapon)///如果物品是武器,那就加角色的伤害(damage)属性                {                    Weapon w = (Weapon)item;                    damage += w.Damage;                }            }        }        strength += player.BasicStrength;        intellect += player.BasicIntellect;        agility += player.BasicAgility;        stamina += player.BasicStamina;        damage += player.BasicDamage;        string text = string.Format("力量:{0}\n智力:{1}\n敏捷:{2}\n体力:{3}\n攻击力:{4}\n", strength, intellect, agility, stamina, damage);        characterPropertyText.text = text;    }    //直接穿戴功能(不需拖拽)    public void PutOn(Item item)     {        Item exitItem = null;//临时保存需要交换的物品        foreach (Slot slot in slotArray)//遍历角色面板中的物品槽,查找合适的的物品槽        {            EquipmentSlot equipmentSlot = (EquipmentSlot)slot;            if (equipmentSlot.IsRightItem(item)) //判断物品是否合适放置在该物品槽里            {                if (equipmentSlot.transform.childCount > 0)//判断角色面板中的物品槽合适的位置是否已经有了装备                {                    ItemUI currentItemUI = equipmentSlot.transform.GetChild(0).GetComponent<ItemUI>();                    exitItem = currentItemUI.Item;                    currentItemUI.SetItem(item, 1);                }                else                {                    equipmentSlot.StoreItem(item);                }                break;            }        }        if (exitItem != null)        {            Knapscak.Instance.StoreItem(exitItem);//把角色面板上是物品替换到背包里面        }        UpdatePropertyText();//更新显示角色属性值    }    //脱掉装备功能(不需拖拽)    public void PutOff(Item item)     {        Knapscak.Instance.StoreItem(item);//把角色面板上是物品替换到背包里面        UpdatePropertyText();//更新显示角色属性值    }}

⑤商店小贩面板

using UnityEngine;using System.Collections;public class Vendor : Inventroy {    //单例模式    private static Vendor _instance;    public static Vendor Instance    {        get        {            if (_instance == null)            {                _instance = GameObject.Find("VendorPanel").GetComponent<Vendor>();            }            return _instance;        }    }    public int[] itemIdArray;//一个物品ID的数组,用于给商贩初始化    private Player player;//对主角Player脚本的引用,用于购买物品功能    public override void Start()    {        base.Start();        InitShop();        player = GameObject.FindWithTag("Player").GetComponent<Player>();        Hide();    }    //初始化商贩    private void InitShop()     {        foreach (int itemId in itemIdArray)        {            StoreItem(itemId);        }    }    //主角购买物品    public void BuyItem(Item item)     {        bool isSusscess = player.ConsumeCoin(item.BuyPrice);//主角消耗金币购买物品        if (isSusscess)        {            Knapscak.Instance.StoreItem(item);        }    }    //主角售卖物品    public void SellItem()     {        int sellAmount = 1;//销售数量        if (Input.GetKey(KeyCode.LeftControl))//按住坐标Ctrl键物品一个一个的售卖,否则全部售卖        {            sellAmount = 1;        }        else        {            sellAmount = InventroyManager.Instance.PickedItem.Amount;        }        int coinAmount = InventroyManager.Instance.PickedItem.Item.SellPrice * sellAmount;//售卖所获得的金币总数        player.EarnCoin(coinAmount);//主角赚取到售卖物品的金币        InventroyManager.Instance.ReduceAmountItem(sellAmount);//鼠标上的物品减少或者销毁    }}

⑥锻造面板

using UnityEngine;using System.Collections;using System.Collections.Generic;/// <summary>/// 锻造类:实现材料锻造成装备或者武器/// </summary>public class Forge : Inventroy {    //单例模式    private static Forge _instance;    public static Forge Instance    {        get        {            if (_instance == null)            {                _instance = GameObject.Find("ForgePanel").GetComponent<Forge>();            }            return _instance;        }    }    private List<Formula> formulaList = null;//用来存放解析出来的材料    public override void Start()    {        base.Start();        ParseFormulaJSON();        Hide();    }    //解析武器锻造配方Jso文件    public void ParseFormulaJSON()    {        formulaList = new List<Formula>();        TextAsset formulaText = Resources.Load<TextAsset>("Formulas");        string formulaJson = formulaText.text;        JSONObject jo = new JSONObject(formulaJson);        foreach (JSONObject temp in jo.list)        {            int item1ID = (int)temp["Item1ID"].n;            int item1Amount = (int)temp["Item1Amount"].n;            int item2ID = (int)temp["Item2ID"].n;            int item2Amount = (int)temp["Item2Amount"].n;            int resID = (int)temp["ResID"].n;            Formula formula = new Formula(item1ID, item1Amount, item2ID, item2Amount, resID);            formulaList.Add(formula);        }        //Debug.Log(formulaList[1].ResID);    }    /// <summary>    /// 锻造物品功能:重点    /// </summary>    public void ForgeItem()     {        //得到当前锻造面板里面有哪些材料        List<int> haveMaterialIDList = new List<int>();//存储当前锻造面板里面拥有的材料的ID        foreach (Slot  slot in slotArray)        {            if (slot.transform.childCount > 0)            {                ItemUI currentItemUI = slot.transform.GetChild(0).GetComponent<ItemUI>();                for (int i = 0; i < currentItemUI.Amount; i++)                {                    haveMaterialIDList.Add(currentItemUI.Item.ID);//物品槽里有多少个物品,就存储多少个ID                }            }        }        //Debug.Log(haveMaterialIDList[0].ToString());        //判断满足哪一个锻造配方的需求        Formula matchedFormula = null;        foreach (Formula formula in formulaList)        {            bool isMatch = formula.Match(haveMaterialIDList);            //Debug.Log(isMatch);            if (isMatch)            {                     matchedFormula = formula;                break;            }        }       // Debug.Log(matchedFormula.ResID);        if (matchedFormula != null)        {            Knapscak.Instance.StoreItem(matchedFormula.ResID);//把锻造出来的物品放入背包            //减掉消耗的材料            foreach (int id in matchedFormula.NeedIDList)            {                foreach (Slot slot in slotArray)                {                    if (slot.transform.childCount > 0)                    {                        ItemUI itemUI = slot.transform.GetChild(0).GetComponent<ItemUI>();                        if (itemUI.Item.ID == id && itemUI.Amount > 0)                        {                            itemUI.RemoveItemAmount();                            if (itemUI.Amount <= 0)                            {                                DestroyImmediate(itemUI.gameObject);                            }                            break;                        }                    }                }            }        }    }}
阅读全文
1 0
原创粉丝点击