Unity--背包系统(含锻造和装备系统)

这篇具有很好参考价值的文章主要介绍了Unity--背包系统(含锻造和装备系统)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背包系统Package包git地址:https://github.com/PigerYoung/InventorySystem.git

背包系统离不开物品,因此在设计背包系统时需要将物品(Item)的类图设置好,附上下发UML类图

unity物品系统,unity,游戏引擎

 首先,根据类图可以编写出Item这个父类,因为所有的装备都是继承自Item类的

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() { }//无参构造函数,防止子类在没中没有显式定义构造函数,则会默认调用父类无参数构造
//函数。
}

再依次创建Item的子类,消耗品,装备,武器,材料类 

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()
    { }
}

编写好物品的类后,用json的格式来创建出各种物品,然后再在代码中解析json,就可以达到解析出的json会把物品的各种信息赋值好,(简单方式就是将各种类的脚本挂载在物品上,制作成预制件,直接使用预制件(因为预制件保存了游戏对象的各种信息,这里json 的作用就是保存装备的各种信息),但是这种方法只适合装备数量不多的情况)(Litjson在解析文件时会区分大小写!!,因此json文件的字段名称应于类中的名称内容和大小写都应该保持一致)

(!!Listjson在在解析枚举类型时,不能"ItemType": "Consumable"解析这种类型的枚举,会自动解析成字符串,因此有两种解决方案:1.使用ISerializationCallbackReceiver接口,序列化完成后再将字符串转为枚举类型,这中需要类中即包含枚举类型有包含字符串类型(这两个要对应)具体参考参考链接。2.将json格式用int类型来表示,比如Consumable对应的枚举类型int就是0,因此这样写参考链接)

这是部分json文件内容,用来做测试用

[
  {
    "Id": 1,
    "Name": "血瓶",
    "ItemType": 0,
    "Quality": 1,
    "Description": "这是用来加血的",
    "Capicity": 10,
    "BuyPrice": 10,
    "SellPrice": 5,
    "Sprite": "Sprites/Items/hp",
    "Hp": 100,
    "Mp": 0
  }
]

有了json文件后就可以创建InventoryManager类来 解析jison文件和管理,在解析json时,因为只用itemList集合(list中存放的是Item这个父类)来接收各种装备(子类),因此就需要用到动态解析json的方法,也就是用JsonData来接收(它可以把所有信息接收下来),随后再通过json中特定的标识符进行区分后再new出对应的子类对象放进itemList中

为了理清思路,先附上开发到该阶段时,InventoryManager类该有的东西(还未开发完,后续还会添加内容)

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
}

 能够成功读取到json后,就可以进行UI的设计和搭建了

Unity搭建UI(这里就不详细讲解如何搭建,都学背包系统了还不会搭UI的!!!回去多搭几个)

设计UI需要注意的点:Slot和Item分别做成一个预制件,也就是格子和Item物品分开制作,方便后续添加隐藏(添加的思路就是将item设为格子的子物体,随后把局部坐标赋为0;隐藏同理)

目前搭建效果

unity物品系统,unity,游戏引擎

UI搭建好后就可以根据UI来设计脚本,以背包面板举例,就会涉及四个脚本,1.Inventory,2.Knapsack,3.Slot,4.ItemUI (具体功能在脚本中)

1.Inventory类,是面板类的父类,面板类也就是背包面板,箱子面板等,这里以背包面板举例,其中就会有些面板类共有的方法属性,如List物品槽,调用存放物品函数,寻找空槽,寻找于item相同的槽等方法

2.Knapsack类,背包面板特有的方法属性(挂载到背包面板上)

3.Slot类,控制格子的脚本,如将Item存放进格子函数(Inventory类调用),获取slot下的item类型,判断当前槽是否装满某装备(挂载到Slot预制件上)

4.ItemUI类,控制Slot中的Item的UI脚本,其中包括Item和数量,设置Item等(挂载带Item预制件上)

下面附上开发到这个阶段的这个四个脚本的源码

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();
    }


}

其中还有个Player脚本用来模拟装备的生成等操作

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);
        }
    }
}

开发到该阶段,能实现的效果是,按下G键就能生成物品 

unity物品系统,unity,游戏引擎

开发完这个功能就可以开发ToolTip提示功能,UI就做个自适应的文本框即可(这里采用两个Text的采用代码同步的方式)

ToolTip脚本功能比较简单,就负责信息面板的显示,隐藏,和更改信息面板的显示内容,(需要在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;
    }
}

有了提示面板后,就需要触发提示面板的显示和隐藏,也就是当鼠标移入和移出Slot时判断(因此Slot脚本还需要实现两个鼠标移入移出事件的接口IPointerEnterHandler,IPointerExitHandler,这里还在Item脚本中添加了获取提示面板内容的函数)

Slot脚本添加的内容是: (需实现IPointerEnterHandler,IPointerExitHandler接口)

public void OnPointerExit(PointerEventData eventData)//鼠标移出事件
    {
        if (transform.childCount > 0)
            InventoryManager.Instance.HideToolTip();
    }

    public void OnPointerEnter(PointerEventData eventData)//鼠标移事件
    {
        if(transform.childCount>0)//要格子有item才能显示
        {
            string toolTipText=transform.GetChild(0).GetComponent<ItemUI>().Item.GetToolTipText();
            InventoryManager.Instance.ShowToolTip(toolTipText);
        }
        
    }

InventoryManager脚本需添加的内容:

 private ToolTip toolTip;//信息面板

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

 public void ShowToolTip(string content)//调用显示信息面板,并赋值内容
    {
        isToolTipsShow = true;
        toolTip.Show(content);
    }
    public void HideToolTip()
    {
        isToolTipsShow = false;
        toolTip.Hide();
    }

Item中添加的脚本:

 /// <summary>
    /// 得到提示面板应该显示的内容(还没有完善,仅做测试)
    /// </summary>
    /// <returns></returns>
    public virtual string GetToolTipText()
    {
        return Name;
    }

 做到这一步能够实现的效果

unity物品系统,unity,游戏引擎

 可以看见提示面板的显示和隐藏,接下来就是实现提示面板跟随鼠标的效果

就在ToolTip脚本中添加一个设置面板位置的函数,随后在InventoryManager调用即可(这里需要屏幕坐标和rect坐标的转换)

ToolTip脚本添加:

public void SetClocalPosition(Vector3 position)//设置信息面板位置
    {
        transform.localPosition = position;
    }

 InventoryManager脚本添加:

    private bool isToolTipsShow = false;//提示面板是否显示的标志位
    private Canvas canvas;
    private Vector2 toolTipPositionOffset = new Vector2(10, -10);//因为中心轴设置的位置的原因,因此要有个偏差才能达到合适的效果

  private void Update()//在update中坐标转换并调用设置面板位置
    {
        if(isToolTipsShow)
        {
            Vector2 position;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(canvas.GetComponent<RectTransform>(), Input.mousePosition,null, out position);
            toolTip.SetClocalPosition(position + toolTipPositionOffset);
        }
    }

效果:

unity物品系统,unity,游戏引擎

 做到这里,就可以把前面部分json物品信息的部分进行完善一下了,和完善提示面板信息的内容

这是完善后json文件的装备配置信息

[
  {
    "Id": 1,
    "Name": "血瓶",
    "ItemType": 0,
    "Quality": 1,
    "Description": "这是用来加血的",
    "Capicity": 10,
    "BuyPrice": 10,
    "SellPrice": 5,
    "Sprite": "Sprites/Items/hp",
    "Hp": 100,
    "Mp": 0
  },
  {
    "Id": 2,
    "Name": "蓝瓶",
    "ItemType": 0,
    "Quality": 1,
    "Description": "这是用来加蓝的",
    "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": "这皮腰带可以加速",
    "Capicity": 1,
    "BuyPrice": 20,
    "SellPrice": 5,
    "Sprite": "Sprites/Items/belts",
    "Strength": 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
  },
  {
    "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": 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": "这是很厉害的戒指",
    "Capicity": 1,
    "BuyPrice": 20,
    "SellPrice": 10,
    "Sprite": "Sprites/Items/rings",
    "Strength": 10,
    "Intellect": 2,
    "Agility": 3,
    "Stamina": 4,
    "equipType": 3
  },
  {
    "Id": 11,
    "Name": "裤子",
    "ItemType": 1,
    "Quality": 1,
    "Description": "这是很厉害的裤子",
    "Capicity": 1,
    "BuyPrice": 40,
    "SellPrice": 20,
    "Sprite": "Sprites/Items/pants",
    "Strength": 20,
    "Intellect": 20,
    "Agility": 20,
    "Stamina": 40,
    "equipType": 4
  },
  {
    "Id": 12,
    "Name": "护肩",
    "ItemType": 1,
    "Quality": 4,
    "Description": "这是很厉害的护肩",
    "Capicity": 1,
    "BuyPrice": 100,
    "SellPrice": 20,
    "Sprite": "Sprites/Items/shoulders",
    "Strength": 20,
    "Intellect": 30,
    "Agility": 40,
    "Stamina": 40,
    "equipType": 7
  },
  {
    "Id": 13,
    "Name": "黑色切割者",
    "ItemType": 2,
    "Quality": 2,
    "Description": "黑切适合半肉战士",
    "Capicity": 1,
    "BuyPrice": 50,
    "SellPrice": 20,
    "Sprite": "Sprites/Items/axe",
    "Damage": 100,
    "weaponType": 1
  },
  {
    "Id": 14,
    "Name": "暴风大剑",
    "ItemType": 2,
    "Quality": 3,
    "Description": "用来合成无尽之刃",
    "Capicity": 1,
    "BuyPrice": 100,
    "SellPrice": 50,
    "Sprite": "Sprites/Items/sword",
    "Damage": 50,
    "weaponType": 0
  },
  {
    "Id": 15,
    "Name": "黑切的合成秘籍",
    "ItemType": 3,
    "Quality": 5,
    "Description": "用来锻造黑切",
    "Capicity": 2,
    "BuyPrice": 100,
    "SellPrice": 99,
    "Sprite": "Sprites/Items/book"
  },
  {
    "Id": 16,
    "Name": "头盔的合成秘籍",
    "ItemType": 3,
    "Quality": 0,
    "Description": "用来锻造头盔",
    "Capicity": 2,
    "BuyPrice": 50,
    "SellPrice": 10,
    "Sprite": "Sprites/Items/scroll"
  },
  {
    "Id": 17,
    "Name": "铁块",
    "ItemType": 3,
    "Quality": 0,
    "Description": "用来锻造其他东西的材料",
    "Capicity": 20,
    "BuyPrice": 5,
    "SellPrice": 4,
    "Sprite": "Sprites/Items/ingots"
  }
]

 完善Item脚本中的GetToolTipText()方法,写为虚方法是为了指向不同种类的物品会显示不同的内容

 /// <summary>
    /// 得到提示面板应该显示的内容
    /// </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>\n购买价格:{1}出售价格:{2}\n<color=yellow>{3}</color>", Name, BuyPrice, SellPrice, Description,color);
        return text;
    }

 随后再各个Item子脚本中重写GetToolTipText()方法,到达不同的效果

如消耗品Consumable脚本中,重写GetToolTipText()方法

 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;
    }

 后续的如装备,材料等信息的展示内容同理,具体重写的方法就不一一展示(可以参考最终版代码中的内容)

unity物品系统,unity,游戏引擎

 从这里开始由于是背包系统的附加功能,不展示阶段性的功能代码任何实现的,如有需要去看最终源码

 做到这里,后续就是需要做装备的点击于拖动了,装备的拖动

这里的大概设计思想就是,创建一个Item的对象来跟随鼠标移动,并且用它来表示拾取到的物品,如果拾取到物品pickedItem就会变成Slot中的Item,那么对应的Slot中的物品就应该销毁或者减少,重点就在于Slot中鼠标按下时对当前点击的Slot的Item和已经跟随着鼠标的Item进行比较判断(还有丢弃物品功能)

unity物品系统,unity,游戏引擎

unity物品系统,unity,游戏引擎

 箱子面板,面板的显示和隐藏,目前能到达的效果,由于代码耦合度较高,比较复杂,因此就不附上功能阶段性代码(因为该部分也不算是背包系统的重点),该部分重点在于介绍思想,如果想看源码,在文章最后有最终开发完全的源码

unity物品系统,unity,游戏引擎

角色面板,功能包括对应槽只能穿戴对应装备,点击鼠标右键一键穿戴装备,一键卸载,装备替换等

unity物品系统,unity,游戏引擎

 开发角色属性数据,通过遍历角色面板中所有的Slot中的Item属性,定义一个更新函数,函数内容是遍历角色面板中的所有Slot中的Item属性,并相加(因此就不用做是穿戴装备还是脱去装备的区分)unity物品系统,unity,游戏引擎

 接下来就是做商店功能,功能有买,卖商品,全部卖出和部分卖出的功能

unity物品系统,unity,游戏引擎

锻造系统,锻造系统的设计需要一个配方类,配方类需要有材料的id数量还有合成结果的id,随后用json格式生成配置文件,json文件的内容就是一个存放配方类的数组;锻造功能的核心在于点击锻造时,利用配方数组进行匹配(算法关键在于两个List的匹配,自身手中物品的List和秘籍需要的物品的List)

unity物品系统,unity,游戏引擎

 保存加载功能,该部分功能主要原理就是将面板中的所有格子中的item读取成字符串的形式储存(每一个格子的内容都需要存储),随后读取时用Split进行分格,根据不同的字符串内容最后进行不同的操作unity物品系统,unity,游戏引擎

 到这里整个背包系统就完结了,从背部系统的附加功能都没有附上代码,可以去参考源码!!(源码里面有详细的注释,推荐看看源码)

梳理一下思路,背包系统核心功能的设计

1.首先就是Item类的设计,item类是一个父类,所有的武器类,装备类,补给品类等都是继承自Item(区分物品的唯一标识就是ID),并且武器类,装备类等又有各自的特有属性

2.在设计完各个物品类后,就需要将物品的配置信息等读取到游戏中,将物品的信息进行配置成json文件,随后解析到游戏中;因为json配置的文件都是Item的各个子类,想要用一个集合把所有的Item子类都保存下来,那么就需要创建一个itemList<Item>这个List集合,接收的对象为Item类(item的子类也可以放进去,这里参考向上转型),这样就用一个父类List存放了所有子类装备(具体实现参考上方文章内容)

3.解析完所有的装备信息后,就是需要设计物品槽和物品的搭建,实现面板和物品之间的交互比如移动物品,获得物品等,是将物品槽和物品都做成单独的预制件,在实现交互等功能(比如将物品储存在槽中,逻辑就是将Item设为槽的子物体,随后将局部坐标变为0就能实现),这里有需要创建多个面板的话(比如背包,商店等面板),就需要有个Inventory父类(是所有面板的父类),子类不同的面板有不同的功能,就可以单独设置文章来源地址https://www.toymoban.com/news/detail-769879.html

到了这里,关于Unity--背包系统(含锻造和装备系统)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 使用团结引擎开发Unity 3D射击游戏

           本案例是初级案例,意在引导想使用unity的初级开发者能较快的入门,体验unity开发的方便性和简易性能。       本次我们将使用团结引擎进行开发,帮助想体验团结引擎的入门开发者进行较快的环境熟悉。      本游戏是一个俯视角度的射击游戏。主角始终位于屏幕

    2024年01月19日
    浏览(78)
  • Unity、UE、Cocos游戏开发引擎的区别

    Unity、Unreal Engine(UE)和Cocos引擎是三个常用的游戏开发引擎,它们在功能和特性上有一些区别。以下是它们之间的主要区别: 编程语言:Unity使用C#作为主要的编程语言,开发者可以使用C#脚本进行游戏逻辑编写。Unreal Engine主要使用C++作为编程语言,但也支持蓝图系统,允许

    2024年02月22日
    浏览(66)
  • Unity 3D期末大作业--背包系统

    1. 功能描述 该部分主要实现了游戏中玩家在个人背包和游戏角色之间切换装备,能够从背包中将装备装到游戏角色上也能够将游戏角色的装备卸下放入背包。 卸下装备放入背包 将背包中装备赋给游戏角色 2. 实现思路 本功能无需3D效果,只需要在UI上进行涉及即可,因此主要

    2024年02月06日
    浏览(44)
  • Unity 农场 1 —— 环境搭建、背包系统、时间系统

    目录 搭建初始地图环境 素材预处理 遮挡层级效果 景观的半遮挡与透明 人物移动 绘制瓦片地图 碰撞层 添加摄像机的边界 (Editor)使用 UI Toolkit 和 UI Builder 制作物品编辑器【待解决】  背包系统 背包数据初始化 InventoryManager——总库存管理 实现地图上显示数据库中的物品

    2024年02月08日
    浏览(44)
  • Unity vs Godot :哪个游戏引擎更适合你?

    游戏引擎的选择对开发过程和最终产品质量有着重大影响。近年来,Godot和Unity这两款引擎受到广泛关注。本文将从多个维度对两者进行比较,以期为开发者提供正确的选择建议。 Godot和Unity都有各自的优势,没有绝对的好坏之分。Godot开源免费,上手简单,更适合2D和小型游戏

    2024年01月23日
    浏览(98)
  • 30分钟了解所有引擎组件,132个Unity 游戏引擎组件速通!【收藏 == 学会】

    🎬 博客主页:https://xiaoy.blog.csdn.net 🎥 本文由 呆呆敲代码的小Y 原创,首发于 CSDN 🙉 🎄 学习专栏推荐:Unity系统学习专栏 🌲 游戏制作专栏推荐:游戏制作 🌲Unity实战100例专栏推荐:Unity 实战100例 教程 🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! 📆 未来很长

    2024年02月11日
    浏览(74)
  • Unity背包系统与存档(附下载链接)

    下载地址: https://download.csdn.net/download/qq_58804985/88184776 视频演示: 功能: 拖动物品在背包中自由移动,当物品拖动到其他物品上时,和其交换位置.基于EPPlus的背包数据与位置保存 原理: 给定一个道具池表格与一个背包表格 道具池表格负责存储所有道具的信息 背包表格负责存储将玩

    2024年02月13日
    浏览(42)
  • Unity之背包系统(轻松储存10万条数据)

    @作者 : SYFStrive @博客首页 : HomePage 📌: 个人社区(欢迎大佬们加入) 👉: 社区链接🔗 📌: 觉得文章不错可以点点关注 👉: 专栏连接🔗 💃: 程序员每天坚持锻炼💪 🔗: 点击直接阅读文章 👉 Unity算法相关文章 (🔥) 博主累了,休息一会💤(可以先看看代码原理

    2024年02月11日
    浏览(34)
  • Unity Physics2D 2d物理引擎游戏 笔记

    2d 材质 里面可以设置 摩擦力 和 弹力 Simulated:是否在当前的物理环境中模拟,取消勾选该框类似于Disable Rigidbody,但使用这个参数更加高效,因为Disable会销毁内部产生的GameObject,而取消勾选Simulated只是禁用。 Kinematic 动力学刚体 动力学刚体不受重力和力的影响,而受用户的

    2023年04月24日
    浏览(124)
  • Unity和UE4两大游戏引擎,你该如何选择?

    目录 游戏引擎 2 —— 难易区别 编程语言 3 —— 游戏产品 UE4制作的游戏产品  Unity制作的游戏产品  产品类型 5 —— 资源商店 6 —— 人才需求 平均薪资 总结      Unity和UE4都是游戏引擎,所谓游戏引擎就是集成了复杂功能的游戏开发软件,他们帮我们实现了复杂的底层逻

    2023年04月08日
    浏览(73)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包