Unity--backpack system (including forging and equipment system)

Backpack system Package git address: https://github.com/PigerYoung/InventorySystem.git

The backpack system is inseparable from items. Therefore, when designing the backpack system, you need to set up the class diagram of the item (Item) and attach the UML class diagram for distribution.

 First of all, the parent class Item can be written according to the class diagram, because all equipment inherits from the Item class

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

public enum ItemType//物品种类
{
    Consumable,//消耗品
    Equipment,//装备
    Weapon,//武器
    Material//材料
}
public enum Quality//物品品质
{
    Common,
    Uncommon,
    Rare,
    Epic,
    Legendary,
    Artifact
}

public class Item //物品基类
{
    public int ID { get; set; }
    public string Name { get; set; }
    public ItemType ItemType { get; set; }
    public Quality Quality { get; set; }
    public string Description { get; set; }
    public int Capicity { get; set; }
    public int BuyPrice { get; set; } 
    public int SellPrice { get;set; }
    public string Sprite { get; set; }//存放物品的图片路径,通过Resources加载
    public Item(int iD, string name, ItemType itemType, Quality quality, string description, int capicity, int buyPrice, int sellPrice)
    {
        ID = iD;
        Name = name;
        ItemType = itemType;
        Quality = quality;
        Description = description;
        Capicity = capicity;
        BuyPrice = buyPrice;
        SellPrice = sellPrice;
        Sprite = sprite;
    }
public Item() { }//无参构造函数,防止子类在没中没有显式定义构造函数,则会默认调用父类无参数构造
//函数。
}

Then create subcategories of Item, consumables, equipment, weapons, and material categories in sequence. 

using UnityEngine;

/// <summary>
/// 消耗品类
/// </summary>
public class Consumable : Item
{
    public int HP { get; set; }//消耗品增加的血量
    public int Mp { get; set; }//消耗品增加的蓝量
    public Consumable(int hP, int mp, int iD, string name, ItemType itemType, Quality quality, string description, int capicity, int buyPrice, int sellPrice,string sprite) :base(iD,name,itemType,quality,description,capicity,buyPrice,sellPrice, sprite)
    {
        HP = hP;
        Mp = mp;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public enum EquipType//装备类型枚举
{
    Head,//头部
    Neck,//脖子
    Ring,//戒指
    Leg,//腿
    Bracer,//护腕
    Boots,//靴子
    Shoulder,//肩膀
    Belt,//腰带
    OffHand//副手
}
/// <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 EquipType equipType { get; set; }//装备类型 
    public Equipment(int strength, int intellect, int agility, int stamina, EquipType equipType, int iD, string name, ItemType itemType, Quality quality, string description, int capicity, int buyPrice, int sellPrice,string sprite): base(iD, name, itemType, quality, description, capicity, buyPrice, sellPrice, sprite)
    {
        Strength = strength;
        Intellect = intellect;
        Agility = agility;
        Stamina = stamina;
        this.equipType = equipType;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEditor.Playables;
using UnityEngine;

/// <summary>
/// 武器类
/// </summary>
public enum WeaponType//武器类型
{
    offHand,//副手
    mianHand//主手
}

public class Weapon : Item
{
    public int Damage { get; set; }
    public WeaponType weaponType { get; set;}

    public Weapon(int damage ,WeaponType weaponType,int iD, string name, ItemType itemType, Quality quality, string description, int capicity, int buyPrice, int sellPrice,string sprite) : base(iD, name, itemType, quality, description, capicity, buyPrice, sellPrice, sprite)
    {
       Damage = damage;
       this.weaponType = weaponType;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 材料类
/// </summary>
public class Material : Item
{
public Material(int iD, string name, ItemType itemType, Quality quality, string description, int capicity, int buyPrice, int sellPrice, string sprite) : base(iD, name, itemType, quality, description, capicity, buyPrice, sellPrice, sprite)
    {

    }
    public Material()
    { }
}

After writing the item classes, use json format to create various items, and then parse the json in the code, you can achieve that the parsed json will assign various information of the items (the simple way is to The script of the class is mounted on the item, made into a prefab, and used directly (because the prefab saves various information about the game object, and the role of json here is to save various information about the equipment), but this method is only suitable for When the number of equipment is not large) (Litjson will be case sensitive when parsing the file!! Therefore, the field name of the json file should be consistent with the name content and case in the class)

(!! Listjson cannot parse this type of enumeration with "ItemType": "Consumable" when parsing the enumeration type, and will automatically parse it into a string, so there are two solutions: 1. Use the ISerializationCallbackReceiver interface to serialize After completion, convert the string into an enumeration type. This requires that the class contains both the enumeration type and the string type (these two must correspond). Please refer to the reference link for details . 2. Use the int type to represent the json format. For example, the enumeration type int corresponding to Consumable is 0, so write the reference link like this )

This is part of the json file content, used for testing

[
  {     "Id": 1,     "Name": "Blood Bottle",     "ItemType": 0,     "Quality": 1,     "Description": "This is used to increase blood",     "Capicity": 10,     " BuyPrice": 10,     "SellPrice": 5,     "Sprite": "Sprites/Items/hp",     "Hp": 100,     "Mp": 0   } ]












After having the json file, you can create the InventoryManager class to parse and manage the json file. When parsing the json, because only the itemList collection (the parent class of Item is stored in the list) is used to receive various equipment (subclasses), so You need to use the method of dynamically parsing json, that is, using JsonData to receive it (it can receive all the information), and then distinguish it through specific identifiers in json, and then new the corresponding subclass object and put it into itemList.

In order to clarify the idea, first attach the things that the InventoryManager class should have when the development reaches this stage (it has not been developed yet, and content will be added later)

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using LitJson;
using System;

public class InventoryManager : MonoBehaviour
{
    #region 单例模式
    private static InventoryManager _instance;
    public static InventoryManager Instance
    {
        get 
        {
            if( _instance == null )
            {
                _instance = GameObject.Find("InventoryManager").GetComponent<InventoryManager>();//这里是在静态方法中,因此不能直接用this或者gameobject来获取组件
            }
            return _instance;
        }
    }
    #endregion

    #region 解析json
    //这里设计的大概思想就像,首先json文件是一个写好的装备信息,改json文件是一个[{},{}],数组里面的类是继承自Item的,因此设定一个itemList集合
    //将json文件解析到itemList(解析json到数组需要用到Litjson,unity内置的jsonutility不能解析成数组),如果使用itemList = JsonMapper.ToObject<List<Item>>(itemsjson);
    //会出现一个问题,就是虽然能够成功解析到内容,但是因为是json数组里面存放的是Item的子类对象,子类有特定的一些属性就不能成功解析到itemList 集合的对象中(因为itemList存放的是Item对象,是父类对象),因此也就访问不到
    //因此就需要动态解析json,也就是把所有的json信息都要解析出来,不能只将json解析为Item对象,因此就可以使用JsonData类,来接受json的解析,并且通过判断每一个对象的itemtype来newItem的子对象,并add到itemLis中(子类向上转型);如果要使用itemList对象时,就需要向下转型成对应的子类对象
    private List<Item> itemList = new List<Item>();

    private void Start()
    {
        ParseItemJson();
    }
    //解析物品信息
    void ParseItemJson()
    { 
        TextAsset itemText = Resources.Load<TextAsset>("Items");
        string itemsjson = itemText.text;//物品信息的json格式
        //itemList=JsonUtility.FromJson<List<Item>>(itemsjson);//jsonuti不能解析成数组
        JsonData jsondata = JsonMapper.ToObject(itemsjson);
        //itemList = JsonMapper.ToObject<List<Item>>(itemsjson);//将json解析到itemList中,用一个父类List集合保存所有子类对象(我觉得这里有设计缺陷)
        Item itemtemp = null;                                    
        for (int i=0; i<jsondata.Count;i++)//用物品类型来区分
        {
            int id = (int)jsondata[i]["Id"];
            string name = jsondata[i]["Name"].ToString();
            ItemType itemType = (ItemType)((int)jsondata[i]["ItemType"]);
            Quality quality = (Quality)((int)jsondata[i]["Quality"]);
            string description = jsondata[i]["Description"].ToString();
            int capicity = (int)jsondata[i]["Capicity"];
            int buyprice = (int)jsondata[i]["BuyPrice"];
            int sellprice = (int)jsondata[i]["SellPrice"];
            string sprite = jsondata[i]["Sprite"].ToString();
            switch (itemType)
            {
                case ItemType.Consumable:
                    int hp = (int)jsondata[i]["Hp"];
                    int mp = (int)jsondata[i]["Mp"];
                    itemtemp = new Consumable(hp, mp, id, name, itemType, quality, description, capicity, buyprice, sellprice, sprite);
                    break;
                case ItemType.Equipment:
                    break;
                case ItemType.Weapon:
                    break;
                case ItemType.Material:
                    break;
                default:
                    break;
            }
            itemList.Add(itemtemp);
        }
        Consumable test = (Consumable)itemList[0];
        Debug.Log(test.HP + "+" + test.Mp);
    }
    #endregion
}

 After successfully reading json, you can design and build the UI.

Unity builds UI (I won’t explain how to build it in detail here, I have learned the backpack system and still don’t know how to build a UI!!! Go back and build more)

Points to note when designing the UI: Slot and Item are made into a prefab respectively, that is, the grid and Item items are made separately to facilitate subsequent addition and hiding (the idea of ​​adding is to set the item as a sub-object of the grid, and then assign the local coordinates to 0; same as hiding)

Current build effect

After the UI is built, you can design the script according to the UI. Taking the backpack panel as an example, it will involve four scripts, 1.Inventory, 2.Knapsack, 3.Slot, 4.ItemUI (the specific functions are in the script)

1. The Inventory class is the parent class of the panel class. The panel class is also a backpack panel, a box panel, etc. Here we take the backpack panel as an example. There are some method attributes common to the panel class, such as List item slots and calling the item storage function. Find empty slots, find slots with the same item, etc.

2.Knapsack class, unique method attributes of the backpack panel (mounted on the backpack panel)

3. Slot class, a script that controls the grid, such as storing items into the grid function (called by the Inventory class), obtaining the item type under the slot, and determining whether the current slot is filled with certain equipment (mounted on the Slot prefab)

4. ItemUI class, which controls the UI script of the Item in the Slot, including the Item and quantity, setting the Item, etc. (mounted on the Item prefab)

Attached below are the source codes of the four scripts developed to this stage.

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

/// <summary>
/// 所有可以装物品面板的父类,用来装物品
/// </summary>
public class Inventory : MonoBehaviour
{
    //所有装物品的面板都有Slot,因此可以用list集合来存放当前面板的所有slot
    private List<Slot> slotList = new List<Slot>();
   public virtual void Start()//因为还有背包,箱子等面板可能会用到Start函数,所以把它设为虚函数
    {
        slotList.AddRange(GetComponentsInChildren<Slot>());
    }

/// <summary>
/// 存储物品函数
/// </summary>
/// <param name="id">存储id对应的Item</param>
/// <returns>是否存放成功</returns>
    public bool StoreItem(int id)
    {
        Item item =InventoryManager.Instance.GetItemById(id);
        if (item == null)
        {
            Debug.LogWarning("要储存的物品id不存在");
            return false;
        }
        //如果要存储的物品id存在
        if(item.Capicity==1)//如果容量为1
        {
            //放在一个新格子里面
            Slot slot=FindEmptySlot();
            if (slot==null)
            {
                Debug.LogWarning("没有空的物品槽");
                return false;
            }
            else
            {
                slot.StoreItem(item);//把物品存储到空物品槽里面
            }
        }
        else//如果容量不为1
        {
              //找一个和item的id一样的格子进行存放
            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()//找空的物品槽Slot
    {
        foreach (Slot slot in slotList)
        {
            if(slot.transform.childCount==0)
            {
                return slot;
            }
        }
        return null;
    }
   private Slot FindSameIdSlot(Item item)//找物品槽存放的item与参数itemID相同的slot
    {
        foreach (Slot slot in slotList)
        {
            if(slot.transform.childCount>=1&&slot.GetItemId()==item.Id&&slot.IsFilled()==false)
            {
                return slot;
            }
        }
        return null;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Knapsack : Inventory
{
    #region 单例模式
    private static Knapsack _instance;
    public static Knapsack Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = GameObject.Find("KnapsackPanel").GetComponent<Knapsack>();//这里是在静态方法中,因此不能直接用this或者gameobject来获取组件
            }
            return _instance;
        }
    }
    #endregion
}

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


/// <summary>
/// 这是存储物品的格子脚本
/// </summary>
public class Slot : MonoBehaviour
{
    public GameObject itemPrefab;//这里需要用预制件进行赋值
   public void StoreItem(Item item)//将Item存储到slot格子中(把item放在自身下面),1.如果有item了就,amount++。2.如果没有item,就实例化item放在下面
    {
        if(transform.childCount==0)//如果格子为空时
        {
            GameObject itemGameObject=Instantiate(itemPrefab);
            itemGameObject.transform.SetParent(transform);
            itemGameObject.transform.localPosition = Vector3.zero;
            itemGameObject.GetComponent<ItemUI>().SetItem(item);//!!!这里就是将外部的item和slot中的item同步
        }
        else
        {
            transform.GetChild(0).GetComponent<ItemUI>().AddAmount();
        }
    }

   public int GetItemId()//获取到slot下的Item的Id
    {
        return transform.GetChild(0).GetComponent<ItemUI>().Item.Id;
    }

    public bool IsFilled()//判断当前槽是否装满该装备
    {
        ItemUI itemUI = transform.GetChild(0).GetComponent<ItemUI>();
        return itemUI.Amount >= itemUI.Item.Capicity;
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

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

    private Image itemImage;//item中图片和数量
    private Text amountText;

    private void Awake()
    {
        itemImage = GetComponent<Image>();
        amountText=GetComponentInChildren<Text>();
    }

    public void SetItem(Item item,int amount=1)//用参数item设置itemUI中的item
    {
        this.Item = item;
        this.Amount= amount;
        //更新UI
        itemImage.sprite = Resources.Load<Sprite>(item.Sprite);//根据item中的sprite加载Resources文件中的图片并赋值给当前slot中的item
         if(item.Capicity>1)//容量大于1才显示
        amountText.text=Amount.ToString();
        else 
            amountText.text="";
    }
    public void AddAmount(int amount=1)
    {
        this.Amount += amount;
        //更新UI
        amountText.text = Amount.ToString();
    }


}

There is also a Player script used to simulate the generation of equipment and other operations.

using UnityEngine;

public class Player : MonoBehaviour
{
    void Update()
    {
        //G 按下G键,随机得到一个物品到背包中
        if (Input.GetKeyDown(KeyCode.G))
        {
            int id = Random.Range(1, 2);//通过生成装备id来表示生成装备
            Knapsack.Instance.StoreItem(id);
        }
    }
}

At this stage of development, the effect that can be achieved is that items can be generated by pressing the G key. 

After developing this function, you can develop the ToolTip prompt function, and the UI can be made into an adaptive text box (here, two Texts are used to synchronize the code)

The ToolTip script function is relatively simple and is responsible for displaying, hiding, and changing the display content of the information panel (needs to be called in InventoryManager)

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;
    private float smoothing = 6f;
    private void Start()
    {
        toolTipText = GetComponent<Text>();
        contentText=transform.Find("Content").GetComponent<Text>();
        canvasGroup = GetComponent<CanvasGroup>();
    }
    private void Update()
    {
        if(canvasGroup.alpha!=targetAlpha)
        {
            canvasGroup.alpha = Mathf.MoveTowards(canvasGroup.alpha, targetAlpha, smoothing * Time.deltaTime);
            if(Mathf.Abs(canvasGroup.alpha-targetAlpha)<0.01f)
            {
                canvasGroup.alpha=targetAlpha;
            }
        }
    }
    public void Show(string text)//显示提示信息
    {
        targetAlpha = 1;
        toolTipText.text = text;
        contentText.text = text;
    }
    public void Hide()//隐藏提示信息
    {
        targetAlpha = 0;
    }
}

After you have the prompt panel, you need to trigger the display and hiding of the prompt panel, that is, when the mouse moves into and out of the Slot, it is judged (so the Slot script also needs to implement two interfaces for mouse movement in and out events, IPointerEnterHandler and IPointerExitHandler, and here is also the Item script. A function to obtain the contents of the prompt panel has been added)

The content added by the Slot script is: (need to implement the IPointerEnterHandler, IPointerExitHandler interface)

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


    public void OnPointerEnter(PointerEventData eventData)//Mouse move event
    {         if(transform.childCount>0)//The grid must have an item to display         {             string toolTipText=transform.GetChild(0).GetComponent<ItemUI>().Item.GetToolTipText ();             InventoryManager.Instance.ShowToolTip(toolTipText);         }     }





        

What needs to be added to the InventoryManager script:

 private ToolTip toolTip;//Information panel

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

 public void ShowToolTip(string content)//Call the display information panel and assign the content
    {         isToolTipsShow = true;         toolTip.Show(content);     }     public void HideToolTip()     {         isToolTipsShow = false;         toolTip.Hide();     }







Script added in Item:

 /// <summary>
    /// Get the content that the prompt panel should display (not yet complete, just for testing)
    /// </summary>
    /// <returns></returns>
    public virtual string GetToolTipText()
    {         return Name;     }

 The effect that can be achieved by doing this step

 You can see the display and hiding of the prompt panel. The next step is to achieve the effect of the prompt panel following the mouse.

Just add a function to set the panel position in the ToolTip script, and then call it in the InventoryManager (this requires conversion of screen coordinates and rect coordinates)

ToolTip script adds:

public void SetClocalPosition(Vector3 position)//Set the information panel position
    {         transform.localPosition = position;     }

 InventoryManager script adds:

    private bool isToolTipsShow = false;//The flag that prompts whether the panel is displayed
    private Canvas canvas;
    private Vector2 toolTipPositionOffset = new Vector2(10, -10);//Because of the position set by the central axis, there must be a deviation to achieve this suitable effect

  private void Update()//Coordinate conversion in update and call to set panel position
    {         if(isToolTipsShow)         {             Vector2 position;             RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.GetComponent<RectTransform>(), Input.mousePosition,null, out position);             toolTip .SetClocalPosition(position + toolTipPositionOffset);         }     }






Effect:

 By doing this, you can improve the previous part of the json item information, and improve the content of the prompt panel information.

This is the equipment configuration information of the improved json file.

[
  {     "Id": 1,     "Name": "Blood Bottle",     "ItemType": 0,     "Quality": 1,     "Description": "This is used to increase blood",     "Capicity": 10,     " BuyPrice": 10,     "SellPrice": 5,     "Sprite": "Sprites/Items/hp",     "Hp": 100,     "Mp": 0   },   {     "Id": 2,     "Name": "Blue Bottle ",     "ItemType": 0,     "Quality": 1,     "Description": "This is for adding blue",     "Capicity": 10,     "BuyPrice": 10,     "SellPrice": 5,     "Sprite": "Sprites/Items/mp",     "Hp": 0,     "Mp": 10   },   {


























    "Id": 3,
    "Name": "胸甲",
    "ItemType": 1,
    "Quality": 2,
    "Description": "这是一个胸甲",
    "Capicity": 1,
    "BuyPrice": 20,
    "SellPrice": 5,
    "Sprite": "Sprites/Items/armor",
    "Strength": 10,
    "Intellect": 4,
    "Agility": 9,
    "Stamina": 1,
    "equipType": 2
  },
  {     "Id": 4,     "Name": "皮腰带",     "ItemType": 1,     "Quality": 3,     "Description":"This leather belt can speed up",     "Strength": 1,     "Sprite": "Sprites/Items/belts",     "SellPrice": 5,     "BuyPrice": 20,     "Capicity": 1,










    "Intellect": 6,
    "Agility": 10,
    "Stamina": 10,
    "equipType": 8
  },
  {     "Id": 5,     "Name": "靴子",     "ItemType": 1,     "Quality": 4,     "Description": "这靴子带可以加速",     "Capicity": 1,     "BuyPrice": 20,     "SellPrice": 10,     "Sprite": "Sprites/Items/boots",     "Strength": 10,     "Intellect": 5,     "Agility": 0,     "Stamina": 10,     "equipType": 6   },     "Description": "This bracer can increase defense",     "Quality": 2,     "ItemType": 1,     "Name": "Wristband",     "Id": 6,   {





















    "Capicity": 1,
    "BuyPrice": 20,
    "SellPrice": 10,
    "Sprite": "Sprites/Items/bracers",
    "Strength": 1,
    "Intellect": 2,
    "Agility": 3,
    "Stamina": 4,
    "equipType": 5
  },
  {
    "Id": 6,
    "Name": "护腕",
    "ItemType": 1,
    "Quality": 2,
    "Description": "这个护腕可以增加防御",
    "Capicity": 1,
    "BuyPrice": 20,
    "SellPrice": 10,
    "Sprite": "Sprites/Items/bracers",
    "Strength": 1,
    "Intellect": 2,
    "Agility": 3,
    "Stamina": 4,
    "equipType": 5
  },
  {
    "Id": 7,
    "Name": "神奇手套",
    "ItemType": 1,
    "Quality": 0,
    "Description": "这是暴击拳套",
    "Capicity": 1,
    "BuyPrice": 20,
    "SellPrice": 5,
    "Sprite": "Sprites/Items/gloves",
    "Strength": 1,
    "Intellect": 2,
    "Agility": 3,
    "Stamina": 4,
    "equipType": 9
  },
  {
    "Id": 8,
    "Name": "头盔",
    "ItemType": 1,
    "Quality": 5,
    "Description": "这是头盔",
    "Capicity": 1,
    "BuyPrice": 10,
    "SellPrice": 5,
    "Sprite": "Sprites/Items/helmets",
    "Strength": 1,
    "Intellect": 2,
    "Agility": 3,
    "Stamina": 4,
    "equipType": 0
  },
  {
    "Id": 9,
    "Name": "项链",
    "ItemType": 1,
    "Quality": 5,
    "Description": "这是很厉害的项链",
    "Capicity": 1,
    "BuyPrice": 10,
    "SellPrice": 5,
    "Sprite": "Sprites/Items/necklace",
    "Strength": 1,
    "Intellect": 2,
    "Agility": 3,
    "Stamina": 4,
    "equipType": 1
  },

  {
    "Id": 10,
    "Name": "戒指",
    "ItemType": 1,
    "Quality": 0,
    "Description": "This is a very powerful ring",
    "Capicity": 1,
    "BuyPrice": 20,
    "SellPrice": 10,
    "Sprite": "Sprites/Items/rings",
    "Strength": 10,
    " Intellect": 2,
    "Agility": 3,
    "Stamina": 4,
    "equipType": 3
  },
  {     "Id": 11,     "Name": "Pants",     "ItemType": 1,     "Quality": 1 ,     "Description": "These are awesome pants",     "Capicity": 1,     "BuyPrice": 40,     "SellPrice": 20,     "Sprite": "Sprites/Items/pants",     "Strength": 20,     "Intellect": 20,     "Agility": 20,     "Stamina": 40,













    "equipType": 4
  },
  {     "Id": 12,     "Name": "Shoulder Pads",     "ItemType": 1,     "Quality": 4,     "Description": "This is a very powerful shoulder pad",     " Capicity": 1,     "BuyPrice": 100,     "SellPrice": 20,     "Sprite": "Sprites/Items/shoulders",     "Strength": 20,     "Intellect": 30,     "Agility": 40,     "Stamina" : 40,     "equipType": 7   },   {     "Id": 13,     "Name": "Black Cutter",     "ItemType": 2,     "Quality": 2,     "Description": "Black cut suitable for half-meat warriors",     "Capicity": 1,     "BuyPrice": 50,     "SellPrice": 20,
























    "Sprite": "Sprites/Items/axe",
    "Damage": 100,
    "weaponType": 1
  },
  {     "Id": 14,     "Name": "Storm Greatsword",     "ItemType": 2,     "Quality ": 3,     "Description": "Used to craft the Infinity Blade",     "Capicity": 1,     "BuyPrice": 100,     "SellPrice": 50,     "Sprite": "Sprites/Items/sword",     "Damage" : 50,     "weaponType": 0   },   {     "Id": 15,     "Name": "Black Kiri's Synthesis Cheats",     "ItemType": 3,     "Quality": 5,     "Description": "Used to forge black cuts",     "Capicity": 2,     "BuyPrice": 100,     "SellPrice": 99,





















    "Sprite": "Sprites/Items/book"
  },
  {     "Id": 16,     "Name": "Helm's crafting recipe",     "ItemType": 3,     "Quality": 0,     "Description": "Used Forged Helmet",     "Capicity": 2,     "BuyPrice": 50,     "SellPrice": 10,     "Sprite": "Sprites/Items/scroll"   },   {     "Id": 17,     "Name": "Iron" ,     "ItemType": 3,     "Quality": 0,     "Description": "Material used to forge other things",     "Capicity": 20,     "BuyPrice": 5,     "SellPrice": 4,     "Sprite": "Sprites/Items/ingots"   } ]





















 Improve the GetToolTipText() method in the Item script. It is written as a virtual method to point to different types of items and display different contents.

 /// <summary>
    /// Get the content that the prompt panel should display
    /// </summary>
    /// <returns></returns>
    public virtual string GetToolTipText()
    {         string color = "";         switch (Quality)         {             case Quality.Common:                 color = "white";                 break;             case Quality.Uncommon:                 color = "lime";                 break;             case Quality.Rare:                 color = "navy";                 break;             case Quality.Epic:                 color = "magenta";                 break;















            case Quality.Legendary:
                color = "orange";
                break;
            case Quality.Artifact:
                color = "red";
                break;
        }

        string text = string.Format("<color={4}>{0}</color>\nBuy price:{1}Sell price:{2}\n<color=yellow>{3}</color> ", Name, BuyPrice, SellPrice, Description, color);
        return text;
    }

 Then rewrite the GetToolTipText() method in each Item subscript to achieve different effects.

For example, in the consumable script, override the GetToolTipText() method

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

 The subsequent display of information such as equipment, materials, etc. is the same, and the specific rewriting methods will not be shown one by one (you can refer to the content in the final version of the code)

 Since this is an additional function of the backpack system, any implementation of the staged function code will not be shown. If necessary, go to the final source code.

 After achieving this, the next step is to click and drag the equipment. Drag the equipment

The general design idea here is to create an Item object to follow the mouse movement and use it to represent the picked item. If the picked item is picked up, the pickedItem will become the Item in the Slot, then the corresponding item in the Slot should be To destroy or reduce, the key point is to compare and judge the item of the currently clicked slot and the item that has followed the mouse when the mouse is pressed in the slot (there is also the function of discarding items)

 The box panel, the display and hiding of the panel, the effect that can be achieved currently, due to the high degree of code coupling and complexity, so the functional stage code is not attached (because this part is not the focus of the backpack system), the focus of this part It’s about introducing the idea. If you want to see the source code, there is the fully developed source code at the end of the article.

Character panel, functions include only corresponding equipment can be worn in corresponding slots, right-clicking the mouse to wear equipment with one click, uninstalling with one click, equipment replacement, etc.

 Develop character attribute data by traversing the Item attributes in all Slots in the character panel and defining an update function. The content of the function is to traverse the Item attributes in all Slots in the character panel and add them up (so there is no need to do whether to wear equipment or Distinguish between taking off equipment)

 The next step is to create the store function, which includes the functions of buying and selling goods, selling all and partially selling.

Forging system, the design of the forging system requires a recipe class. The recipe class needs the ID number of the material and the ID of the synthesis result. Then the configuration file is generated in json format. The content of the json file is an array storing the recipe class; the forging function The core is to use the formula array for matching when you click on forging (the key to the algorithm lies in the matching of two lists, the list of items in your hand and the list of items required for cheats)

 Save and load function, the main principle of this part of the function is to read the items in all the grids in the panel and store them in the form of strings (the content of each grid needs to be stored), and then use Split to divide the grids according to different The string content finally performs different operations

 The entire backpack system is complete here. There is no code attached to the additional functions of the back system. You can refer to the source code ! ! (There are detailed comments in the source code, it is recommended to read the source code)

To sort out the ideas, the design of the core functions of the backpack system

1. The first is the design of the Item class. The item class is a parent class. All weapon classes, equipment classes, supply categories, etc. are inherited from Item (the only identifier to distinguish items is the ID), and the weapon classes, equipment classes, etc. are also have their own unique properties

2. After designing each item class, you need to read the configuration information of the item into the game, configure the item information into a json file, and then parse it into the game; because the json configuration files are all items of the item. Subclass, if you want to use a collection to save all Item subclasses, then you need to create an itemList<Item> List collection, and the received object is the Item class (subclasses of item can also be put in, here refer to the above Transformation), so that a parent class List is used to store all subclass equipment (for specific implementation, please refer to the article above)

3. After parsing all the equipment information, you need to design the item slots and the construction of the items to realize the interaction between the panel and the items, such as moving items, obtaining items, etc. The item slots and items are made into separate prefabricated parts. When implementing functions such as interaction (such as storing items in a slot, the logic is to set the Item as a sub-object of the slot, and then change the local coordinates to 0), if there is a need to create multiple panels (such as backpacks, stores and other panels), you need to have an Inventory parent class (which is the parent class of all panels). Panels with different subclasses have different functions and can be set separately.

Guess you like

Origin blog.csdn.net/qq_62947569/article/details/131741190