背包系统 装备系统和锻造系统 - 基于Unity2018 UGUI

设计物品的UML类图

开发Item物品类

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

//物品基类
public class Item 
{
    public int ID { get; set; }
    public string Name { get; set; }
    public ItemType Type { get; set; }
    public ItemQuality Quality { get; set; }
    public string Description { get; set; }
    public int Capacity { get; set; }
    public int BuyPrice { get; set; }
    public int SellPrice { get; set; }

    public Item(int id,string name,ItemType type,ItemQuality quality,string des,int capacity,int buyPrice,int sellPirce)
    {
        this.ID = id;
        this.Type = type;
        this.Quality = quality;
        this.Description = des;
        this.Capacity = capacity;
        this.BuyPrice = buyPrice;
        this.SellPrice = sellPirce;

    }


    //物品类型
    public enum ItemType
    {
        Consumable,
        Equipment,
        Weapon,
        Material
    }
    //品质
    public enum ItemQuality
    {
        Common,
        UnCommon,
        Rare,
        Epic,
        Legendary,
        Artifact
    }
}


开发消耗品类、装备类、武器类和材料类

在Item类添加一个新的构造方法

    public Item()
    {
        this.ID = -1;
    }

消耗品类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
/// <summary>
/// 消耗品类
/// </summary>
public class Consumable : Item
{
    public int HP { get; set; }
    public int MP { get; set; }

    public Consumable(int id, string name, ItemType type, ItemQuality quality, string des, int capacity, int buyPrice, int sellPirce,int hp,int mp)
        : base(id, name, type, quality, des, capacity, buyPrice, sellPirce)
    {
        this.HP = hp;
        this.MP = mp;
    }
}

装备类

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

/// <summary>
/// 装备类
/// </summary>
public class Equipment : Item
{
    public int Strength { get; set; }//力量
    public int Intellect { get; set; }//智力  
    public int Agility { get; set; }//敏捷
    public int Stamina { get; set; }//体力
    public EquipmentType EquipType { get; set; }

    public Equipment(int id, string name, ItemType type, ItemQuality quality, string des, int capacity, int buyPrice, int sellPirce,int strength,int intellect,int agility,int stamina,EquipmentType equipType)
        :base(id, name, type, quality, des, capacity, buyPrice, sellPirce)
    {
        this.Strength = strength;
        this.Intellect = intellect;
        this.Agility = agility;
        this.Stamina = stamina;
        this.EquipType = equipType;
    }


    public enum EquipmentType
    {
        Head,
        Neck,
        Ring,
        Leg,
        Bracer,
        Boots,
        Trinket,
        Shoulder,
        Belt,
        OffHand,
    }

}

武器类

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

/// <summary>
/// 武器类
/// </summary>
public class Weapon : Item
{
    public int Damage { get; set; }

    public WeaponType WpType;

    public Weapon(int id, string name, ItemType type, ItemQuality quality, string des, int capacity, int buyPrice, int sellPirce,int damage,WeaponType wpType)
        :base(id, name, type, quality, des, capacity, buyPrice, sellPirce)
    {
        this.Damage = damage;
        this.WpType = wpType;
    }

    public enum WeaponType
    {
        OffHand,
        MainHand
    }
}

材料类

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

/// <summary>
/// 材料类
/// </summary>
public class Material : Item
{
   
}

设计物品类的Json文件

通过下面的网址在线设计Json文件

http://www.bejson.com/jsoneditoronline/

设计一个药品类的Json文件

[
    {
        "id": 1,
        "name": "血瓶",
        "type": "Consumable",
        "quality": "Common",
        "description": "这个是用来加血的",
        "capacity": 10,
        "buyPrice": 10,
        "sellPrice": 5,
        "hp": 10,
        "mp": 0,
        "sprite": "Sprites/Items/hp"
    }
]

开发InventoryManager物品管理器

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

public class InventoryManager : MonoBehaviour
{
    //单例模式
    private static InventoryManager _instance;

    public static InventoryManager Instance
    {
        get
        {
            if(_instance == null)
            {
                //下面的代码只会执行一次
                _instance = GameObject.Find("InventoryManager").GetComponent<InventoryManager>();
            }
            return _instance;
        }
    }
}

Json解析过程

使用JSONObject来进行解析

    /// <summary>
    /// 解析物品信息
    /// </summary>
    void ParseItemJson()
    {
        itemList = new List<Item>();
        //文本在Untiy里面是 TextAsset类型
        TextAsset itemText = Resources.Load("Items") as TextAsset;
        string itemsJson = itemText.text;
        JSONObject j = new JSONObject(itemsJson);
        foreach (JSONObject temp in j.list)
        {
            Item.ItemType type = (Item.ItemType)System.Enum.Parse(typeof(Item.ItemType), temp["type"].str);
            
            //下面解析这个对象里面的公有属性
            int id = (int)(temp["id"].n);
            string name = temp["name"].str;
            Item.ItemQuality quality = (Item.ItemQuality)System.Enum.Parse(typeof(Item.ItemQuality), temp["quality"].str);
            string description = temp["description"].str;
            int capacity = (int)(temp["capacity"].n);
            int buyPrice = (int)(temp["buyPrice"].n);
            int sellPrice = (int)(temp["sellPrice"].n);
            string sprite = temp["sprite"].str;

            Item item = null;

            switch (type)
            {
                case Item.ItemType.Consumable:
                    int hp = (int)(temp["hp"].n);
                    int mp = (int)(temp["mp"].n);
                    item = new Consumable(id, name, type, quality, description, capacity, buyPrice, sellPrice, sprite, hp, mp);
                    break;
                case Item.ItemType.Equipment:
                    //TODO
                    break;
                case Item.ItemType.Weapon:
                    //TODO
                    break;
                case Item.ItemType.Material:
                    //TODO
                    break;
            }
            itemList.Add(item);
            Debug.Log(item);
        }
    }

设计背包的UI

开发Slot和Item的Prefab预制体

更改Knapsack和Chest的设计

定义一个Inventory类

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

public class Inventory : MonoBehaviour
{

    private Slot[] slotList;

     virtual public void Start()
    {
        slotList = GetComponentsInChildren<Slot>();
    }


}

给Inventory添加物品存储的功能

首先在InventoryManager中添加一个通过id寻找物品的办法

    public Item GetItemById(int id)
    {
        foreach (Item item in itemList)
        {
            if(item.ID == id)
            {
                return item;
            }
        }
        return null;
    }

在Inventory里面添加物品存储的代码,首先考虑需要新的空格子存储的情况

   public bool StoreItem(int id)
    {
        Item item = InventoryManager.Instance.GetItemById(id);
        return StoreItem(item);
    }

    public bool StoreItem(Item item)
    {
        if(item == null)
        {
            Debug.Log("要存储的物品id不存在");
            return false;
        }
        if(item.Capacity == 1)
        {
            //TODO
            Slot slot = FindEmptySlot();
            if (slot == null)
            {
                Debug.Log("没有新的物品槽可以添加物品。");
            }
            else
            {
                slot.StoreItem(item);//把物品存储到这个空的物品槽里面
            }
        }
        else
        {

        }
    }

    /// <summary>
    /// 这个方法用来寻找新的物品槽
    /// </summary>
    /// <returns></returns>
    private Slot FindEmptySlot()
    {
        foreach (Slot slot in slotList)
        {
            if(slot.transform.childCount == 0)
            {
                return slot;
            }
        }
        return null;
    }
}

完善物品存储功能

给ItemUI中定义两个属性

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

public class ItemUI : MonoBehaviour
{
    public Item Item { get; set; }
    public int Amount { get; set; }
}

然后在Slot里面 添加三个方法 ,分别是存储item,得到当前存储item的类型以及是否超过容量。

    /// <summary>
    /// 把item放在自身下面
    /// 如果自身下面已经有item了,amount++
    /// 如果没有,根据itemPrefab去实例化一个item,放在下面
    /// </summary>
    /// <param name="item"></param>
    public void StoreItem(Item item)
    {

    }

    /// <summary>
    /// 得到当前物品槽存储的物品类型
    /// </summary>
    public Item.ItemType GetItemType()
    {
        return transform.GetChild(0).GetComponent<ItemUI>().Item.Type;
    }

    /// <summary>
    /// Is Slot Filled?
    /// </summary>
    /// <returns></returns>
    public bool IsFilled()
    {
        ItemUI itemUI = transform.GetChild(0).GetComponent<ItemUI>();
        return itemUI.Amount >= itemUI.Item.Capacity;//当前的数量大于等于容量
    }

在Inventory中完善物品存储功能

    public bool StoreItem(Item item)
    {
        if(item == null)
        {
            Debug.Log("要存储的物品id不存在");
            return false;
        }
        if(item.Capacity == 1)
        {
            //TODO
            Slot slot = FindEmptySlot();
            if (slot == null)
            {
                Debug.Log("没有新的物品槽可以添加物品。");
                return false;
            }
            else
            {
                slot.StoreItem(item);//把物品存储到这个空的物品槽里面
            }
        }
        else
        {
            Slot slot = FindSameTypeSlot(item);
            if(EmptySlot != null)
            {
                slot.StoreItem(item);
            }
            else
            {
                Slot EmptySlot = FindEmptySlot();
                if(slot != null)
                {
                    EmptySlot.StoreItem(item);
                }
                else
                {
                    Debug.Log("没有新的物品槽可以添加物品。");
                    return false;
                }
            }
        }
        return true;
    }



    private Slot FindSameTypeSlot(Item item)
    {
        foreach (Slot slot in slotList)
        {
            if(slot.transform.childCount>=1 && slot.GetItemType() == item.Type && slot.IsFilled() == false)
            {
                return slot;
            }
        }
        return null;
    }

开发Slot的StoreItem存储功能

首先在ItemUI里面添加两个方法,一个用来设置Item里面的属性,一个用来更新数量

    public void SetItem(Item item,int amount = 1)
    {
        this.Item = item;
        this.Amount = amount;
        //UpdateUI
    }

    public void AddAmount(int amout = 1)
    {
        this.Amount += amout;
        //UpdateUI
    }

完善Slot的StoreItem存储功能

    /// <summary>
    /// 把item放在自身下面
    /// 如果自身下面已经有item了,amount++
    /// 如果没有,根据itemPrefab去实例化一个item,放在下面
    /// </summary>
    /// <param name="item"></param>
    public void StoreItem(Item item)
    {
        if(transform.childCount == 0)
        {
            GameObject itemGameObject = Instantiate(itemPrefab) as GameObject;
            itemGameObject.transform.SetParent(this.transform);
            itemGameObject.transform.localPosition = Vector3.zero;
            itemGameObject.GetComponent<ItemUI>().SetItem(item);
        }
        else
        {
            transform.GetChild(0).GetComponent<ItemUI>().AddAmount();
        }
    }

测试背包物品存储功能

新建一个Player物体用来进行测试

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

public class Player : MonoBehaviour
{
    // Update is called once per frame
    void Update()
    {
        //F 随机得到一个物品放到背包里面
        if (Input.GetKeyDown(KeyCode.F))
        {
            int id = Random.Range(1, 2);
            Knapsack.Instance.StoreItem(id);
        }
    }
}

背包中物品的UI更新显示

在ItemUI中添加两个属性

    private Image itemImage;
    private Text amountText;

    private Image ItemImage
    {
        get
        {
            if(itemImage == null)
            {
                itemImage = GetComponent<Image>();
            }
            return itemImage;
        }
    }

    private Text AmountText
    {
        get
        {
            if(amountText == null)
            {
                amountText = GetComponentInChildren<Text>();
            }
            return amountText;
        }
    }

在ItemUI里添加更新图片和数字的方法

    public void SetItem(Item item, int amount = 1)
    {
        this.Item = item;
        this.Amount = amount;
        ItemImage.sprite = Resources.Load<Sprite>(item.Sprite);
        AmountText.text = Amount.ToString();
    }

    public void AddAmount(int amout = 1)
    {
        this.Amount += amout;
        AmountText.text = Amount.ToString();
    }

设计ToolTip的UI

添加一个Content Size Fitter组件,让其自适应

开发ToolTip类控制提示信息显示和隐藏

新建一个ToolTip脚本,添加控制提示信息显示和隐藏的办法,通过CanvasGroup里的Alpha来实现

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

public class ToolTip : MonoBehaviour
{
    private Text toolTipText;
    private Text contentText;
    private CanvasGroup canvasGroup;

    private float targetAlpha = 0;

    public float smoothing = 1;

    private void Start()
    {
        toolTipText = GetComponent<Text>();
        contentText = transform.Find("Content").GetComponent<Text>();
        canvasGroup = GetComponent<CanvasGroup>();
    }

    private void Update()
    {
        if(canvasGroup.alpha != targetAlpha)
        {
            Mathf.Lerp(canvasGroup.alpha, targetAlpha, smoothing * Time.deltaTime);
            if(Mathf.Abs( canvasGroup.alpha - targetAlpha) < 0.01f)
            {
                canvasGroup.alpha = targetAlpha;
            }
        }
    }

    public void Show(string text)
    {
        toolTipText.text = text;
        contentText.text = text;
        targetAlpha = 1;
    }

    public void Hide()
    {
        targetAlpha = 0;
    }
}

把ToolTip交给InventoryManager进行管理

    private ToolTip toolTip;

    private void Start()
    {
        ParseItemJson();
        toolTip = GameObject.FindObjectOfType<ToolTip>();
    }

    public void ShowToolTip(string content)
    {
        toolTip.Show(content);
    }

    public void HideToolTip()
    {
        toolTip.Hide();
    }

检测鼠标的进入和移除 控制ToolTip的显示和隐藏

在Item里面添加一个显示信息的代码

    /// <summary>
    /// 得到提示面板应该显示什么样的内容
    /// </summary>
    /// <returns></returns>
    public virtual string GetToolTipText()
    {
        return Name +": " + Description;//TODO
    }

在Slot里面添加两个接口,用来处理鼠标的交互

IPointerEnterHandler,IPointerExitHandler

    public void OnPointerEnter(PointerEventData eventData)
    {
        if (transform.childCount > 0)
        {
            string toolTipText = transform.GetChild(0).GetComponent<ItemUI>().Item.GetToolTipText();
            InventoryManager.Instance.ShowToolTip(toolTipText);
        }     
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        if (transform.childCount > 0)
            InventoryManager.Instance.HideToolTip();
    }

控制提示信息面板的跟随

添加一个isToolTipShow变量,用来给ToolTip当标志

    private bool isToolTipShow = false;
    public void ShowToolTip(string content)
    {
        isToolTipShow = true;
        toolTip.Show(content);
    }

    public void HideToolTip()
    {
        isToolTipShow = false;
        toolTip.Hide();
    }

在Update里边添加跟随的代码

    private Canvas canvas;
    //偏移,为了让ToolTip更好的显示
    public Vector2 toolTipPositionOffset = new Vector2(150, -25);
    private void Update()
    {
        if (isToolTipShow)
        {
            //控制提示面板跟随鼠标
            Vector2 position;
            //获取鼠标的位置
            RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform, Input.mousePosition, null, out position);
            toolTip.SetLocalPositon(position+toolTipPositionOffset);
        }
    }

在ToolTip中添加新方法,用来设置它的位置

    public void SetLocalPositon(Vector3 position)
    {
        transform.localPosition = position;
    }

添加蓝瓶的Json和Fixbug

添加胸甲的Json

[
  {
    "id": 1,
    "name": "血瓶",
    "type": "Consumable",
    "quality": "Common",
    "description": "这个是用来加血的",
    "capacity": 10,
    "buyPrice": 10,
    "sellPrice": 5,
    "hp": 10,
    "mp": 0,
    "sprite": "Sprites/Items/hp"
  },
  {
    "id": 2,
    "name": "蓝瓶",
    "type": "Consumable",
    "quality": "Common",
    "description": "这个是用来加蓝的",
    "capacity": 10,
    "buyPrice": 10,
    "sellPrice": 5,
    "hp": 0,
    "mp": 10,
    "sprite": "Sprites/Items/mp"
  },
  {
    "id": 3,
    "name": "胸甲",
    "type": "Equipment",
    "quality": "Rare",
    "description": "这个胸甲很牛B",
    "capacity": 1,
    "buyPrice": 20,
    "sellPrice": 10,
    "sprite": "Sprites/Items/armor",
    "strength": 10,
    "intellect": 4,
    "agility": 9,
    "stamina": 1,
    "equipType": "Chest"
  }
]

控制装备类型Json信息的解析

                case Item.ItemType.Equipment:
                    int strength = (int)(temp["strength"].n);
                    int intellect = (int)(temp["intellect"].n);
                    int agility = (int)(temp["agility"].n);
                    int stamina = (int)(temp["stamina"].n);
                    Equipment.EquipmentType equipType = (Equipment.EquipmentType)System.Enum.Parse(typeof(Equipment.EquipmentType), temp["equipType"].str);
                    item = new Equipment(id, name, type, quality, description, capacity, buyPrice, sellPrice, sprite, strength, intellect, agility, stamina, equipType);
                    break;

为了让装备数目显示好看,修改ItemUI中的设置方法

        if (Item.Capacity > 1)
            AmountText.text = Amount.ToString();
        else
            AmountText.text = "";

完善所有的装备Json信息

[
  {
    "id": 1,
    "name": "血瓶",
    "type": "Consumable",
    "quality": "Common",
    "description": "这个是用来加血的",
    "capacity": 10,
    "buyPrice": 10,
    "sellPrice": 5,
    "hp": 10,
    "mp": 0,
    "sprite": "Sprites/Items/hp"
  },
  {
    "id": 2,
    "name": "蓝瓶",
    "type": "Consumable",
    "quality": "Common",
    "description": "这个是用来加蓝的",
    "capacity": 10,
    "buyPrice": 10,
    "sellPrice": 5,
    "hp": 0,
    "mp": 10,
    "sprite": "Sprites/Items/mp"
  },
  {
    "id": 3,
    "name": "胸甲",
    "type": "Equipment",
    "quality": "Rare",
    "description": "这个胸甲很牛B",
    "capacity": 1,
    "buyPrice": 20,
    "sellPrice": 10,
    "sprite": "Sprites/Items/armor",
    "strength": 10,
    "intellect": 4,
    "agility": 9,
    "stamina": 1,
    "equipType": "Chest"
  },
  {
    "id": 4,
    "name": "皮腰带",
    "type": "Equipment",
    "quality": "Epic",
    "description": "这个腰带可以加速",
    "capacity": 1,
    "buyPrice": 20,
    "sellPrice": 10,
    "sprite": "Sprites/Items/belts",
    "strength": 1,
    "intellect": 6,
    "agility": 10,
    "stamina": 10,
    "equipType": "Belt"
  },
  {
    "id": 5,
    "name": "靴子",
    "type": "Equipment",
    "quality": "Legendary",
    "description": "这个靴子可以加速",
    "capacity": 1,
    "buyPrice": 20,
    "sellPrice": 10,
    "sprite": "Sprites/Items/boots",
    "strength": 10,
    "intellect": 5,
    "agility": 0,
    "stamina": 10,
    "equipType": "Boots"
  },
  {
    "id": 6,
    "name": "护腕",
    "type": "Equipment",
    "quality": "Rare",
    "description": "这个护腕可以增加防御",
    "capacity": 1,
    "buyPrice": 20,
    "sellPrice": 10,
    "sprite": "Sprites/Items/bracers",
    "strength": 1,
    "intellect": 2,
    "agility": 3,
    "stamina": 4,
    "equipType": "Bracer"
  },
  {
    "id": 7,
    "name": "神启手套",
    "type": "Equipment",
    "quality": "Common",
    "description": "很厉害的手套",
    "capacity": 1,
    "buyPrice": 10,
    "sellPrice": 5,
    "sprite": "Sprites/Items/gloves",
    "strength": 2,
    "intellect": 3,
    "agility": 4,
    "stamina": 4,
    "equipType": "OffHand"
  },
  {
    "id": 8,
    "name": "头盔",
    "type": "Equipment",
    "quality": "Artifact",
    "description": "很厉害的头盔",
    "capacity": 1,
    "buyPrice": 10,
    "sellPrice": 5,
    "sprite": "Sprites/Items/helmets",
    "strength": 2,
    "intellect": 3,
    "agility": 4,
    "stamina": 4,
    "equipType": "Head"
  },
  {
    "id": 9,
    "name": "项链",
    "type": "Equipment",
    "quality": "Rare",
    "description": "很厉害的项链",
    "capacity": 1,
    "buyPrice": 10,
    "sellPrice": 5,
    "sprite": "Sprites/Items/necklace",
    "strength": 2,
    "intellect": 3,
    "agility": 4,
    "stamina": 4,
    "equipType": "Neck"
  },
  {
    "id": 10,
    "name": "戒指",
    "type": "Equipment",
    "quality": "Common",
    "description": "很厉害的戒指",
    "capacity": 1,
    "buyPrice": 20,
    "sellPrice": 20,
    "sprite": "Sprites/Items/rings",
    "strength": 20,
    "intellect": 3,
    "agility": 4,
    "stamina": 4,
    "equipType": "Ring"
  },
  {
    "id": 11,
    "name": "裤子",
    "type": "Equipment",
    "quality": "Uncommon",
    "description": "很厉害的裤子",
    "capacity": 1,
    "buyPrice": 40,
    "sellPrice": 20,
    "sprite": "Sprites/Items/pants",
    "strength": 20,
    "intellect": 30,
    "agility": 40,
    "stamina": 40,
    "equipType": "Leg"
  },
  {
    "id": 12,
    "name": "护肩",
    "type": "Equipment",
    "quality": "Legendary",
    "description": "很厉害的护肩",
    "capacity": 1,
    "buyPrice": 100,
    "sellPrice": 20,
    "sprite": "Sprites/Items/shoulders",
    "strength": 2,
    "intellect": 3,
    "agility": 4,
    "stamina": 4,
    "equipType": "Shoulder"
  }
]

武器Json信息的完善和解析

  {
    "id": 13,
    "name": "开天斧",
    "type": "Weapon",
    "quality": "Rare",
    "description": "渔翁移山用的斧子",
    "capacity": 1,
    "buyPrice": 50,
    "sellPrice": 20,
    "sprite": "Sprites/Items/axe",
    "damage": 100,
    "weaponType": "MainHand"
  },
  {
    "id": 14,
    "name": "阴阳剑",
    "type": "Weapon",
    "quality": "Rare",
    "description": "非常厉害的剑",
    "capacity": 1,
    "buyPrice": 15,
    "sellPrice": 5,
    "sprite": "Sprites/Items/sword",
    "damage": 20,
    "weaponType": "OffHand"
  }

完善解析

                case Item.ItemType.Weapon:
                    int damage = (int)temp["damage"].n;
                    Weapon.WeaponType wpType = (Weapon.WeaponType)System.Enum.Parse(typeof(Weapon.WeaponType), temp["weaponType"].str);
                    item = new Weapon(id, name, type, quality, description, capacity, buyPrice, sellPrice, sprite, damage, wpType);
                    break;

材料Json信息的完善和解析

  {
    "id": 15,
    "name": "开天斧的锻造秘籍",
    "type": "Material",
    "quality": "Artifact",
    "description": "用来锻造开天斧的秘籍",
    "capacity": 2,
    "buyPrice": 100,
    "sellPrice": 99,
    "sprite": "Sprites/Items/book"
  },
  {
    "id": 16,
    "name": "头盔的锻造秘籍",
    "type": "Material",
    "quality": "Common",
    "description": "用来锻造头盔的秘籍",
    "capacity": 2,
    "buyPrice": 50,
    "sellPrice": 10,
    "sprite": "Sprites/Items/scroll"
  },
  {
    "id": 17, 
    "name": "铁块",
    "type": "Material",
    "quality": "Common",
    "description": "用来锻造其他东西的必备材料",
    "capacity": 20,
    "buyPrice": 5,
    "sellPrice": 4,
    "sprite": "Sprites/Items/ingots"
  }

完善解析

                case Item.ItemType.Material:
                    item = new Material(id, name, type, quality, description, capacity, buyPrice, sellPrice, sprite);
                    break;

完善物品的提示信息显示

在Item里面完善物品提示信息显示,让显示变得好看,可以根据装备品质显示不同颜色

    /// <summary>
    /// 得到提示面板应该显示什么样的内容
    /// </summary>
    /// <returns></returns>
    public virtual string GetToolTipText()
    {
        string color = "";
        switch (Quality)        
        {
            case ItemQuality.Common:
                color = "white";
                break;
            case ItemQuality.Uncommon:
                color = "lime";
                break;
            case ItemQuality.Rare:
                color = "navy";
                break;
            case ItemQuality.Epic:
                color = "magenta";
                break;
            case ItemQuality.Legendary:
                color = "orange";
                break;
            case ItemQuality.Artifact:
                color = "red";
                break;
            default:
                break;
        }
        string text = string.Format("<color={4}>{0}</color>\n<size=10><color=green>购买价格:{1} 出售价格:{2}</color></size>\n<color=yellow><size=10>{3}</size></color>", Name, BuyPrice, SellPrice, Description, color);
        return text;
    }
}

完善消耗品、装备和武器的提示信息显示

在消耗品类里添加以下代码

    public override string GetToolTipText()
    {
        string text = base.GetToolTipText();
        string newText = string.Format("{0}\n\n<color=blue>加血:{1}\n加蓝:{2}</color>", text, HP, MP);
        return newText;
    }

在装备类里添加以下代码

    public override string GetToolTipText()
    {
        string text = base.GetToolTipText();
        string equipTypeText = "";
        switch (EquipType)
        {
            case EquipmentType.Head:
                equipTypeText = "头部";
                break;
            case EquipmentType.Neck:
                equipTypeText = "脖子";
                break;
            case EquipmentType.Chest:
                equipTypeText = "胸甲";
                break;
            case EquipmentType.Ring:
                equipTypeText = "戒指";
                break;
            case EquipmentType.Leg:
                equipTypeText = "腿部";
                break;
            case EquipmentType.Bracer:
                equipTypeText = "护腕";
                break;
            case EquipmentType.Boots:
                equipTypeText = "靴子";
                break;
            case EquipmentType.Shoulder:
                equipTypeText = "护肩";
                break;
            case EquipmentType.Belt:
                equipTypeText = "腰带";
                break;
            case EquipmentType.OffHand:
                equipTypeText = "副手";
                break;
            default:
                break;
        }
        string newText = string.Format("{0}\n\n<color=blue>装备类型:{1}\n力量:{2}\n智力:{3}\n敏捷:{4}\n体力:{5}</color>", text, equipTypeText, Strength,Intellect,Agility,Stamina);
        return newText;
    }

在武器类里添加以下代码

    public override string GetToolTipText()
    {
        string text = base.GetToolTipText();
        string wpTypeText = "";
        switch (WpType)
        {
            case WeaponType.OffHand:
                wpTypeText = "副手";
                break;
            case WeaponType.MainHand:
                wpTypeText = "主手";
                break;
        }
        string newText = string.Format("{0}\n\n<color=blue>武器类型:{1}\n攻击力:{2}</color>", text, wpTypeText, Damage);
        return newText;
    }

在InventoryManager添加PickedI

创建一个Item叫做PickedItem用来做鼠标拖拽

    private ItemUI pickedItem;//鼠标选中的物体

首先在Start里面对其进行初始化

        pickedItem = GameObject.Find("PickedItem").GetComponent<ItemUI>();
        pickedItem.Hide();

在ItemUI里面添加要用到的方法

    public void Show()
    {
        gameObject.SetActive(true);
    }

    public void Hide()
    {
        gameObject.SetActive(false);
    }

    public void SetLocalPostion(Vector3 posiiton)
    {
        transform.localPosition = posiiton;
    }

物品移动各种情况分析

使用IPointerDownHandler进行鼠标拖拽,首先分析以下物品移动的各种情况

    public void OnPointerDown(PointerEventData eventData)
    {
        //自身是空 1.pickedItem != null pickedItem放在这个位置
                        //按下ctrl        放置当前鼠标上的物体的一个
                        //没有按下ctrl      放置当前鼠标上的物品的所有
        //         2.pickedItem == null 不做任何处理


        //自身不是空 1.pickedItem != null pickedItem跟当前物品进行交换
                        //自身的id==pickedItem.id
                            //按下ctrl        放置当前鼠标上物品的一个
                            //没有按下ctrl      放置当前鼠标上的物品的所有
                                                //可以完全放下
                                                //只能放下其中一部分
                        //自身的id!=pickedItem.id      pickedItem跟当前物品交换
        //           2.pickedItem == null 把当前物品槽里面的物品放到鼠标上
                            //按下ctrl        取得当前物品槽中物品的一半
                            //没有按下ctrl      取得当前物品槽中物品的所有
                        
    }

处理物品的捡起

    public void OnPointerDown(PointerEventData eventData)
    {
        //自身是空 1.isPickedItem == true pickedItem放在这个位置
                        //按下ctrl        放置当前鼠标上的物体的一个
                        //没有按下ctrl      放置当前鼠标上的物品的所有
        //         2.isPickedItem == false  不做任何处理


        //自身不是空 1.isPickedItem == true pickedItem跟当前物品进行交换
                        //自身的id==pickedItem.id
                            //按下ctrl        放置当前鼠标上物品的一个
                            //没有按下ctrl      放置当前鼠标上的物品的所有
                                                //可以完全放下
                                                //只能放下其中一部分
                        //自身的id!=pickedItem.id      pickedItem跟当前物品交换
        //           2.isPickedItem == false 把当前物品槽里面的物品放到鼠标上
                            //按下ctrl        取得当前物品槽中物品的一半
                            //没有按下ctrl      取得当前物品槽中物品的所有

        if(transform.childCount>0)
        {
            ItemUI currentItem = transform.GetChild(0).GetComponent<ItemUI>();
            if(InventoryManager.Instance.IsPickedItem == false)
            {
                if (Input.GetKey(KeyCode.LeftControl))
                {
                    //TODO
                }
                else
                {                   
                    //把当前物品槽的信息 复制给PickedItem(跟随鼠标移动)
                    InventoryManager.Instance.PickedItem.SetItemUI(currentItem);
                    InventoryManager.Instance.IsPickedItem = true;
                    Destroy(currentItem.gameObject);
                }
            }
        }
    }        

处理物品数量的一半的捡起

在Slot中添加以下代码

            if(InventoryManager.Instance.IsPickedItem == false)
            {
                if (Input.GetKey(KeyCode.LeftControl))
                {
                    int amountPicked = (currentItem.Amount + 1) / 2;//捡起的数量
                    InventoryManager.Instance.PickupItem(currentItem, amountPicked);
                    int amountRemained = currentItem.Amount - amountPicked;
                    if (amountRemained <= 0)
                    {
                        Destroy(currentItem.gameObject);
                    }
                    else
                    {
                        currentItem.SetAmount(amountRemained);
                    }

                }

需要在ItemUI中添加修改数量的方法

    public void SetAmount(int amount)
    {
        this.Amount = amount;
        if (Item.Capacity > 1)
            AmountText.text = Amount.ToString();
        else
            AmountText.text = "";
    }

 在Inventory中添加捡起道具的方法

    //捡起物品槽中所有数量的物品
    public void PickupItem(ItemUI itemUI)
    {
        PickedItem.SetItem(itemUI.Item, itemUI.Amount);
        IsPickedItem = true;
    }

    //捡起物品槽指定数目的物品
    public void PickupItem(ItemUI itemUI,int amount)
    {
        PickedItem.SetItem(itemUI.Item,amount);
        IsPickedItem = true;
    }

控制选中物品跟随鼠标

在InventoryManager中添加控制选择物品跟随鼠标的代码

        if (isPickedItem)
        {
            //如果我们捡起了物品,我们就要让物品跟随鼠标
            //控制提示面板跟随鼠标
            Vector2 position;
            //获取鼠标的位置
            RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.transform as RectTransform, Input.mousePosition, null, out position);
            pickedItem.SetLocalPostion(position);
        }

同时还需要隐藏ToolTip,我们修改下面两个方法

    //捡起物品槽中指定数量的物品
    public void PickupItem(Item item,int amount)
    {
        PickedItem.SetItem(item,amount);
        PickedItem.Show();
        IsPickedItem = true;
        this.toolTip.Hide();
    }


    public void ShowToolTip(string content)
    {
        if (this.isPickedItem) return;
        isToolTipShow = true;
        toolTip.Show(content);
    }

给物品添加显示的动画

在ItemUI中实现动画

    private float targetScale = 1f;
    private Vector3 animationScale = new Vector3(1.4f,1.4f,1.4f);
    private float smoothing = 4;

    private void Update()
    {
        if (transform.localScale.x != targetScale)
        {
            //动画
            float scale = Mathf.Lerp(transform.localScale.x, targetScale, smoothing*Time.deltaTime);
            transform.localScale = new Vector3(scale, scale, scale);
            if(Mathf.Abs(transform.localScale.x - targetScale) < .02f)
            {
                transform.localScale = new Vector3(targetScale, targetScale, targetScale); 
            }
        }
    }

然后在SetItem、AddAmount和SetAmount的方法中添加一条语句,用来初始化动画

        transform.localScale = animationScale;

按下Ctrl一个一个放置物品

在之前的方法中添加以下代码

            else
            {
                //自身是空 1.isPickedItem == true pickedItem放在这个位置
                                //按下ctrl        放置当前鼠标上的物体的一个
                                //没有按下ctrl      放置当前鼠标上的物品的所有
                //         2.isPickedItem == false  不做任何处理
                if(currentItem.Item.ID == InventoryManager.Instance.PickedItem.Item.ID)
                {
                    if (Input.GetKey(KeyCode.LeftControl))
                    {
                        if(currentItem.Item.Capacity > currentItem.Amount)//当前物品槽还有容量
                        {
                            currentItem.AddAmount();
                            InventoryManager.Instance.RemoveOneItem();
                        }
                        else
                        {
                            return;
                        }
                    }
                }

在InventoryManager中添加拿掉一个物品放在物品槽里面的方法

    /// <summary>
    /// 从手上拿掉一个物品放在物品槽里面
    /// </summary>
    public void RemoveOneItem()
    {
        PickedItem.ReduceAmount();
        if (PickedItem.Amount <= 0)
        {
            isPickedItem = false;
            PickedItem.Hide();
        }
    }

在ItemUI中添加减少数量的方法ReduceAmount

    public void ReduceAmount(int amout = 1)
    {
        transform.localScale = animationScale;
        this.Amount -= amout;
        if (Item.Capacity > 1)
            AmountText.text = Amount.ToString();
        else
            AmountText.text = "";
    }

最后不要忘记取消pickedItem上Raycast Target的勾选

物品放置-累加和剩余情况处理

继续完善之前的代码

                        //没有按下ctrl      放置当前鼠标上的物品的所有
                                        //可以完全放下
                                        //只能放下一部分
                    else
                    {
                        if (currentItem.Item.Capacity > currentItem.Amount)
                        {
                            int amountRemain = currentItem.Item.Capacity - currentItem.Amount;//当前物品槽剩余的空间
                            if(amountRemain>= InventoryManager.Instance.PickedItem.Amount)
                            {
                                //可以完全放下
                                currentItem.SetAmount(currentItem.Amount + InventoryManager.Instance.PickedItem.Amount);
                                InventoryManager.Instance.RemoveAllItem();
                            }
                            else
                            {
                                //只能放下一部分
                                currentItem.SetAmount(currentItem.Amount + amountRemain);
                                InventoryManager.Instance.ReMoveItem(amountRemain);
                            }
                        }
                        else
                        {
                            return;
                        }
                    }

在InventoryManager中添加需要的方法

    public void RemoveAllItem()
    {
        isPickedItem = false;
        PickedItem.Hide();
    }

    public void ReMoveItem(int amount)
    {
        PickedItem.ReduceAmount(amount);
    }

处理把物品放到空的物品槽里面

        else
        {
            //自身是空 1.isPickedItem == true pickedItem放在这个位置
            //按下ctrl        放置当前鼠标上的物体的一个
            //没有按下ctrl      放置当前鼠标上的物品的所有
            if (InventoryManager.Instance.IsPickedItem == true)
            {
                if (Input.GetKey(KeyCode.LeftControl))
                {
                    this.StoreItem(InventoryManager.Instance.PickedItem.Item);
                    InventoryManager.Instance.RemoveItem();
                }
                else
                {
                    for (int i = 0; i < InventoryManager.Instance.PickedItem.Amount; i++)
                    {
                        this.StoreItem(InventoryManager.Instance.PickedItem.Item);
                    }
                    InventoryManager.Instance.RemoveItem(InventoryManager.Instance.PickedItem.Amount);
                }
            }
            else
            {
                return;
            }
        }

添加Chest箱子

创建一个箱子,在其上面添加Chest脚本进行管理,让Chest脚本继承Inventory。

处理物品的丢弃

在InventoryManager的Update中添加物品丢弃的方法

        //物品丢弃的处理
        if(isPickedItem && Input.GetMouseButtonDown(0) && UnityEngine.EventSystems.EventSystem.current.IsPointerOverGameObject(-1) == false)
        {
            isPickedItem = false;
            pickedItem.Hide();
        }

控制背包的显示和隐藏

在Inventory中添加下面的代码

    private float targetAlpha = 1;//目标的透明度

    private float smoothing = 4;

    private CanvasGroup canvasGroup;

    virtual public void Start()
    {
        slotList = GetComponentsInChildren<Slot>();
        canvasGroup = GetComponent<CanvasGroup>();
    }

    private void Update()
    {
        if (canvasGroup.alpha != targetAlpha)
        {
            canvasGroup.alpha = Mathf.Lerp(canvasGroup.alpha, targetAlpha, smoothing * Time.deltaTime);
            if(Mathf.Abs(canvasGroup.alpha - targetAlpha) < 0.01f)
            {
                canvasGroup.alpha = targetAlpha;
            }
        }
    }

    public void Show()
    {
        targetAlpha = 1;
    }

    public void Hide()
    {
        targetAlpha = 0;
    }

    public void DisplaySwitch()
    {
        if(targetAlpha == 0)
        {
            Show();
        }
        else
        {
            Hide();
        }
    }

然后在Player里面进行调用

        //B 控制背包的显示的隐藏
        if (Input.GetKeyDown(KeyCode.B))
        {
            Knapsack.Instance.DisplaySwitch();
        }

        //Y 控制箱子的显示的隐藏
        if (Input.GetKeyDown(KeyCode.Y))
        {
            Chest.Instance.DisplaySwitch();
        }

处理物品交换

                    //自身的id!=pickedItem.id      pickedItem跟当前物品交换
                    Item item = currentItem.Item;
                    int amount = currentItem.Amount;
                    currentItem.SetItem(InventoryManager.Instance.PickedItem.Item, InventoryManager.Instance.PickedItem.Amount);
                    InventoryManager.Instance.PickedItem.SetItem(item, amount);

设计角色面板

管理角色面板所有的物品槽

创建一个新的EquipmentSlot类专门管理装备格子

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

public class EquipmentSlot : Slot
{
    public Equipment.EquipmentType equipType;
    public Weapon.WeaponType wpType;

}

给角色面板创建一个CharacterPanel进行管理

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

public class CharacterPanel : Inventory
{
    private EquipmentSlot mainHandSLot;
    private EquipmentSlot offHandSlot;

    public override void Start()
    {
        base.Start();
        mainHandSLot = transform.Find("MainHandSlot").GetComponent<EquipmentSlot>();
        offHandSlot = transform.Find("OffHandSlot").GetComponent<EquipmentSlot>();
    }
}

分析装备拖拽穿戴方式的情况

在EquipmentSlot里重写点击装备槽的方法,首先考虑出现的情况

    public override void OnPointerDown(PointerEventData eventData)
    {
        //手上有 东西
                //当前装备槽有装备
                //无装备
        //手上没东西
                //当前装备槽有装备
                //无装备   不做处理

    }

处理装备的穿戴

在EquipmentSlot中重写点击装备槽的方法

public override void OnPointerDown(PointerEventData eventData)
    {
        //手上有 东西
        //当前装备槽有装备
        //无装备
        //手上没东西
        //当前装备槽有装备
        //无装备   不做处理
        if (InventoryManager.Instance.IsPickedItem == true)
        {
            //手上有东西的情况
            ItemUI pickedItem = InventoryManager.Instance.PickedItem;
            if (transform.childCount > 0)//物品槽有装备
            {
                ItemUI currentItemUI = transform.GetChild(0).GetComponent<ItemUI>();//当前装备槽里面的物品
                if (IsRightItem(pickedItem.Item))
                {
                    //Item item = currentItemUI.Item;
                    //int amount = currentItemUI.Amount;
                    //currentItemUI.SetItem(pickedItem.Item, pickedItem.Amount);
                    //InventoryManager.Instance.PickedItem.SetItem(item, amount);
                    currentItemUI.Exchange(InventoryManager.Instance.PickedItem);
                }
            }
            else
            //手上有装备 物品槽没装备
            {
                if (IsRightItem(pickedItem.Item))
                {
                    this.StoreItem(InventoryManager.Instance.PickedItem.Item);
                    InventoryManager.Instance.RemoveItem(1);
                }

            }
        }
        else
        {

        }

    }

    /// <summary>
    /// 判断item是否合适放在这个位置
    /// </summary>
    private bool IsRightItem(Item item)
    {
        if ((item is Equipment && ((Equipment)(item)).EquipType == this.equipType) ||
                    (item is Weapon && ((Weapon)(item)).WpType == this.wpType))
            return true;
        return false;
    }

装备的穿戴和卸下

完善之前的代码

        else//手上没东西
        {
            if (transform.childCount > 0)//物品槽有装备
            {
                ItemUI currentItemUI = transform.GetChild(0).GetComponent<ItemUI>();
                InventoryManager.Instance.PickupItem(currentItemUI.Item, currentItemUI.Amount);
                Destroy(currentItemUI.gameObject);
            }
        }

处理装备的右击事件

首先给之前Slot和EquipmentSlot里的方法添加左键点击权限

        //使用左键点击才能生效
        if (eventData.button != PointerEventData.InputButton.Left) return;

在Slot里面添加装备的右键点击事件

        //使用右键点击
        if(eventData.button == PointerEventData.InputButton.Right)
        {
            if (InventoryManager.Instance.IsPickedItem == false && transform.childCount > 0)
            {
                ItemUI currentItemUI = transform.GetChild(0).GetComponent<ItemUI>();
                if(currentItemUI.Item is Equipment || currentItemUI.Item is Weapon)
                {
                    currentItemUI.ReduceAmount();
                    Item currentItem = currentItemUI.Item;
                    if (currentItemUI.Amount <= 0)
                    {
                        DestroyImmediate(currentItemUI.gameObject);
                        InventoryManager.Instance.HideToolTip();
                    }
                    CharacterPanel.Instance.PutOn(currentItem);
                }
            }
        }

处理装备的自动穿戴

在CharacterPanel里面添加自动穿戴的方法PutOn

    public void PutOn(Item item)
    {
        Item exitItem = null;
        foreach (Slot slot in slotList)
        {           
            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)
            Knapsack.Instance.StoreItem(exitItem);
    }

处理装备的脱下

首先在EquipmentSlot的事件点击添加右键点击的方法

        //使用右键点击
        if (eventData.button == PointerEventData.InputButton.Right)
        {
            if (InventoryManager.Instance.IsPickedItem == false && transform.childCount > 0)
            {
                ItemUI currentItemUI = transform.GetChild(0).GetComponent<ItemUI>();

                //脱掉装备放到背包里面去
                transform.parent.SendMessage("PutOff", currentItemUI.Item);
                Destroy(currentItemUI.gameObject);
                InventoryManager.Instance.HideToolTip();
            }
        }

在CharacterPanel里面添加脱掉装备的方法PutOff

    public void PutOff(Item item)
    {
        Knapsack.Instance.StoreItem(item);
    }

控制角色面板的显示和隐藏

Player脚本里面 添加下面代码

        //U 控制角色面板的显示和隐藏
        if (Input.GetKeyDown(KeyCode.U))
        {
            CharacterPanel.Instance.DisplaySwitch();
        }

控制角色面板的属性显示

在Character中添加更新属性栏的方法

    private void UpdatePropertyText()
    {
        int strength = 0, intellect = 0, agility = 0, stamina = 0, damage = 0;
        foreach (EquipmentSlot slot in slotList)
        {
            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)
                {
                    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智力:{0}\n敏捷:{0}\n体力:{0}\n攻击力:{4}", strength, intellect, agility, stamina, damage);
        propertyText.text = text;
    }

然后在脱掉装备和穿上装备的地方进行更新。

设计小贩商店

小贩商店中物品的初始化

创建Vendor和VendorSlot脚本

在Vendor里面进行贩卖物品的初始化

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

public class Vendor : Inventory
{
    public int[] itemIdArray;

    public override void Start()
    {
        base.Start();
        InitShop();
    }

    private void InitShop()
    {
        foreach(int itemId in itemIdArray)
        {
            StoreItem(itemId);
        }
    }
}

给角色添加金币属性

在Player里面添加金币属性,然后添加消费金币和赚取金币的方法

    private int coinAmount = 100;

    private Text coinText;

    private void Start()
    {
        coinText = GameObject.Find("Coin").GetComponentInChildren<Text>();
        coinText.text = coinAmount.ToString();
    }

    /// <summary>
    /// 消费金币
    /// </summary>
    public bool ConsumeCoin(int amount)
    {
        if(coinAmount>= amount)
        {
            coinAmount -= amount;
            coinText.text = coinAmount.ToString();
            return true;
        }
        return false;
    }

    /// <summary>
    /// 赚取金币
    /// </summary>
    /// <param name="amount"></param>
    public void EarnCoint(int amount)
    {
        this.coinAmount += amount;
        coinText.text = coinAmount.ToString();
    }

物品购买功能

在VendorSlot中添加物品的购买功能

    public override void OnPointerDown(PointerEventData eventData)
    {
        if(eventData.button == PointerEventData.InputButton.Right &&  InventoryManager.Instance.IsPickedItem == false)
        {
            if (transform.childCount > 0)
            {
                Item currentItem = transform.GetChild(0).GetComponent<ItemUI>().Item;
                transform.parent.parent.SendMessage("BuyItem", currentItem);
            }
        }
    }

Vendor中的购买物品方法BuyItem为

    public void BuyItem(Item item)
    {
        bool isSuccess = player.ConsumeCoin(item.BuyPrice);
        if (isSuccess)
        {
            Knapsack.Instance.StoreItem(item);
        }
    }

物品出售功能

在VendorSlot中出售物品的购能

        else if(eventData.button == PointerEventData.InputButton.Left && InventoryManager.Instance.IsPickedItem == true)
        {
            transform.parent.parent.SendMessage("SellItem");
        }

Vendor中的出售物品方法SellItem为

    public void SellItem()
    {
        int sellAmount = 1;
        if (Input.GetKey(KeyCode.LeftControl))
        {

            sellAmount = 1;
        }
        else
        {
            sellAmount = InventoryManager.Instance.PickedItem.Amount;
        }
        int coinAmount = InventoryManager.Instance.PickedItem.Item.SellPrice * sellAmount;
        player.EarnCoin(coinAmount);
        InventoryManager.Instance.RemoveItem(sellAmount);
    }

设计锻造系统界面

设计锻造系统的秘方类和秘方Json

创建秘方类Formula

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

public class Formula 
{
    public int Item1ID { get; set; }
    public int Item1Amount { get; set; }
    public int Item2ID { get; set; }
    public int Item2Amount { get; set; }

    public int ResID { get; set; }//锻造结果的物品

}

创建秘方Json

[
  {
    "Item1ID": 15,
    "Item1Amount": 1,
    "Item2ID": 17,
    "Item2Amount": 2,
    "ResID": 13
  },
  {
    "Item1ID": 16,
    "Item1Amount": 1,
    "Item2ID": 17,
    "Item2Amount": 5,
    "ResID": 8
  }
]

解析秘方Json

在Forge中完成对秘方Json的解析


    void ParseFormulaJson()
    {
        formulaList = new List<Formula>();
        TextAsset formulasText = Resources.Load<TextAsset>("Formulas");
        string formulasJson = formulasText.text;//物品信息的Json格式
        JSONObject jo = new JSONObject(formulasJson);
        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);

    }

开发物品合成的核心匹配算法

在Forge里面添加锻造按钮的事件ForgeItem

    public void ForgeItem()
    {
        //得到当前拥有哪些材料
        //判断满足哪一个秘籍的要求
        List<int> haveMaterialIDList = new List<int>();//存储当前拥有材料的id
        foreach (Slot slot in slotList)
        {
            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
                }
            }
        }
    }

在Formula里添加锻造物品id匹配的方法

    private List<int> needIdList = new List<int>();//所需要物品的id

    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;
        for (int i = 0; i < Item1Amount; i++)
        {
            needIdList.Add(Item1ID);
        }
        for (int i = 0; i < Item2Amount; i++)
        {
            needIdList.Add(Item2ID);
        }
    }

    /// <summary>
    /// 判断材料是否满足秘籍
    /// </summary>
    public bool Match(List<int> idList)//idList里提供需要合成物品的材料id
    {        
        List<int> tempIDList = new List<int>(idList);
        foreach(int id in needIdList)
        {
            bool isSuccess = tempIDList.Remove(id);
            if(isSuccess == false)
            {
                return false;
            }
        }
        return true;
    }

物品的合成锻造生成处理

完善ForgeItem方法

    public void ForgeItem()
    {
        //得到当前拥有哪些材料
        //判断满足哪一个秘籍的要求
        List<int> haveMaterialIDList = new List<int>();//存储当前拥有材料的id
        foreach (Slot slot in slotList)
        {
            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
                }
            }
        }

        Formula matchedFormula = null;
        foreach(Formula formula in formulaList)
        {
            bool isMatch = formula.Match(haveMaterialIDList);
            if (isMatch)
            {
                matchedFormula = formula;break;
            }
        }
        if (matchedFormula != null)
        {
            Knapsack.Instance.StoreItem(matchedFormula.ResID);
            //去掉消耗的材料
            foreach(int id in matchedFormula.NeedIdList)
            {
                foreach(Slot slot in slotList)
                {
                    if (slot.transform.childCount > 0)
                    {
                        ItemUI itemUI = slot.transform.GetChild(0).GetComponent<ItemUI>();
                        if(itemUI.Item.ID == id && itemUI.Amount > 0)
                        {
                            itemUI.ReduceAmount();
                            if (itemUI.Amount <= 0)
                                DestroyImmediate(itemUI.gameObject);
                            break;
                        }
                    }
                }
            }
        }           
    }

控制锻造界面和商店界面的显示和隐藏

        //I 控制商店的显示和隐藏
        if (Input.GetKeyDown(KeyCode.I))
        {
            Vendor.Instance.DisplaySwitch();
        }

        //O 控制锻造的显示和隐藏
        if (Input.GetKeyDown(KeyCode.O))
        {
            Forge.Instance.DisplaySwitch();
        }

控制物品的存储和加载

在Inventory里面添加控制物品存储和加载的方法

    public void SaveInventory()
    {
        StringBuilder sb = new StringBuilder();
        foreach (Slot slot in slotList)
        {
            if (slot.transform.childCount > 0)
            {
                ItemUI itemUI = slot.transform.GetChild(0).GetComponent<ItemUI>();
                sb.Append(itemUI.Item.ID + "," + itemUI.Amount + "-");                    
            }
            else
            {
                sb.Append("0-");
            }           
        }
        PlayerPrefs.SetString(this.gameObject.name, sb.ToString());
    }

    public void LoadInventory()
    {
        if (PlayerPrefs.HasKey(this.gameObject.name) == false) return;
        string str = PlayerPrefs.GetString(this.gameObject.name);
        string[] itemArray = str.Split('-');
        for(int i = 0; i < itemArray.Length - 1; i++)
        {
            string itemStr = itemArray[i];
            if(itemStr != "0")
            {
                string[] temp = itemStr.Split(',');
                int id = int.Parse(temp[0]);
                Item item = InventoryManager.Instance.GetItemById(id);
                int amount = int.Parse(temp[1]);
                for(int j = 0; j < amount; j++)
                {
                    slotList[i].StoreItem(item);
                }
            }
        }
    }

在InventoryManager中进行调用

    public void SaveInventory()
    {
        Knapsack.Instance.SaveInventory();
        Chest.Instance.SaveInventory();
        CharacterPanel.Instance.SaveInventory();
        Forge.Instance.SaveInventory();
        PlayerPrefs.SetInt("CoinAmount", GameObject.FindGameObjectWithTag("Player").GetComponent<Player>().CoinAmount);
    }

    public void LoadInventory()
    {
        Knapsack.Instance.LoadInventory();
        Chest.Instance.LoadInventory();
        CharacterPanel.Instance.LoadInventory();
        Forge.Instance.LoadInventory();
        if (PlayerPrefs.HasKey("CoinAmount"))
        {
            GameObject.FindGameObjectWithTag("Player").GetComponent<Player>().CoinAmount = PlayerPrefs.GetInt("CoinAmount");
        }
    }

点击保存后终止游戏,重新运行游戏点击加载

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值