Unity类银河战士恶魔城学习总结(P124 CharacterStats UI玩家的UI)

news2024/11/24 6:35:15

【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili

教程源地址:https://www.udemy.com/course/2d-rpg-alexdev/

本章节实现了玩家属性栏,仓库,物品栏UI的制作

UI_StatSlot.cs

这个脚本是用来在Unity的UI上显示玩家属性(比如生命值或攻击力)的。

  1. 显示状态名称statName用来存储属性名称,比如"Health"。在编辑器中修改这个名字时,它会自动显示在对应的UI文本框里。
  2. 显示状态值statValueText是用来显示这个属性的数值(比如100生命值)。
  3. 初始化UIStart方法会在游戏开始时更新UI,确保显示玩家的正确状态。
  4. 动态更新UpdateStatValueUI方法可以随时调用,更新UI上显示的数值。它会通过PlayerManager找到玩家的属性,然后把这个值显示在UI上。
using System.Collections;
using System.Collections.Generic;
using TMPro;
using UnityEngine;

public class UI_StatSlot : MonoBehaviour
{
    [SerializeField] private string statName;
    [SerializeField] private StatType statType;
    [SerializeField] private TextMeshProUGUI statValueText;
    [SerializeField] private TextMeshProUGUI statNameText;

    private void OnValidate()
    {
        gameObject.name = "Stat - "+ statName;

        if(statNameText != null)
            statNameText.text = statName;

    }


    void Start()
    {
        UpdateStatValueUI();
    }


    public void UpdateStatValueUI()
    {
        PlayerStats playerStats = PlayerManager.instance.player.GetComponent<PlayerStats>();

        if(playerStats !=null)
        {
            statValueText.text = playerStats.GetStat(statType).GetValue().ToString();
        }

    }
}

CharacterStats.cs

把状态类型移动到这个脚本

using System.Collections;
using UnityEngine;


public enum StatType//枚举 StatType 的定义
{
    strength,
    agility,
    intelligence,
    vitality,
    damage,
    critChance,
    critPower,
    health,
    armor,
    evasion,
    magicRes,
    fireDamage,
    iceDamage,
    lightingDamage
}


//10月25日
//10月26日
public class CharacterStats : MonoBehaviour
{
    private EntityFX fx;


    [Header("主属性")]
    public Stat strength;//力量,1点增加1攻击力和%1爆伤
    public Stat agility;//敏捷,1点增加1%闪避和%1暴击率
    public Stat intelligence;//智力,1点增加1法术强度和%1魔抗
    public Stat vitality;//活力,1点增加3生命值


    [Header("攻击属性")]//offensive stats
    public Stat damage;
    public Stat critChance;//暴击率
    public Stat critPower;//暴击伤害,默认%150



    [Header("防守属性")]//defensive stats
    public Stat maxHealth;
    public Stat armor;//护甲
    public Stat evasion;//闪避
    public Stat magicResistance;//魔抗


    [Header("魔法属性")]//magic stats
    public Stat fireDamage;
    public Stat iceDamage;
    public Stat lightningDamage;


    public bool isIgnited;//是否燃烧,持续伤害
    public bool isChilled;//是否冻结,削弱护甲20%
    public bool isShocked;//是否感电,减少命中率20%


    [SerializeField] private float ailmentsDuration = 4;//异常状态持续时间
    private float ignitedTimer;
    private float chilledTimer;
    private float shockedTimer;



    private float igniteDamageCoolDown = .3f;//燃烧伤害间隔时间
    private float igniteDamageTimer;//燃烧伤害计时器
    private int igniteDamage;//燃烧伤害
    [SerializeField] private GameObject shockStrikePrefab;
    private int shockDamage;


    public int currentHealth;

    public System.Action onHealthChanged;
    public bool isDead { get; private set; }



    protected virtual void Start()
    {
        critPower.SetDefaultValue(150);//暴击伤害默认150%
        currentHealth = GetMaxHealthValue();//一开始血条满的

        fx = GetComponent<EntityFX>();
    }


    protected virtual void Update()
    {
        ignitedTimer -= Time.deltaTime;//燃烧时间减少
        chilledTimer -= Time.deltaTime;
        shockedTimer -= Time.deltaTime;

        igniteDamageTimer -= Time.deltaTime;//燃烧伤害计时器减少


        if (ignitedTimer < 0)
            isIgnited = false;


        if (chilledTimer < 0)
            isChilled = false;


        if (shockedTimer < 0)
            isShocked = false;

        if (isIgnited)
            ApplyIgniteDamage();
    }



    public virtual void IncreaseStatBy(int _modifier, float _duration, Stat _statToModify)
    {
        StartCoroutine(StatModCoruntine(_modifier, _duration, _statToModify));
    }


    private IEnumerator StatModCoruntine(int _modifier, float _duration, Stat _statToModify)//加buff的协程
    {
        _statToModify.AddModifier(_modifier);//添加一个buff

        yield return new WaitForSeconds(_duration);

        _statToModify.RemoveModifier(_modifier);//移除一个buff
    }


    public virtual void DoDamage(CharacterStats _targetStats)//只是一次物理攻击
    {
        if (TargetCanAvoidAttack(_targetStats))
            return;

        int totalDamage = damage.GetValue() + strength.GetValue();

        if (Cancrit())
        {
            //Debug.Log("Crit Hit");
            totalDamage = CalculateCriticalDamage(totalDamage);
            //Debug.Log(" 总的暴击伤害是"+ totalDamage);//Total crit damage is
        }


        totalDamage = CheckTargetArmor(_targetStats, totalDamage);
        _targetStats.TakeDamage(totalDamage);//把造成的给到继承CharacterStats的类


        DoMagicDamage(_targetStats);//如果普通攻击不想要魔法伤害移除

    }




    #region Magic Damage and ailments

    public virtual void DoMagicDamage(CharacterStats _targetStats)//只是一次魔法攻击
    {

        int _fireDamage = fireDamage.GetValue();
        int _iceDamage = iceDamage.GetValue();
        int _lightningDamage = lightningDamage.GetValue();



        int totalMagicalDamage = _fireDamage + _iceDamage + _lightningDamage + intelligence.GetValue();
        totalMagicalDamage = CheckTargetResistance(_targetStats, totalMagicalDamage);

        _targetStats.TakeDamage(totalMagicalDamage);//把造成的给到继承CharacterStats的类


        //important
        if (Mathf.Max(_fireDamage, _iceDamage, _lightningDamage) <= 0)//可以保证下面的while循环不会无限循环
            return;


        AttempToApplyAilements(_targetStats, _fireDamage, _iceDamage, _lightningDamage);

    }

    private void AttempToApplyAilements(CharacterStats _targetStats, int _fireDamage, int _iceDamage, int _lightningDamage)
    {
        //判断魔法伤害类型
        bool canApplyIgnite = _fireDamage > _iceDamage && _fireDamage > _lightningDamage;
        bool canApplyChill = _iceDamage > _fireDamage && _iceDamage > _lightningDamage;
        bool canApplyShock = _lightningDamage > _fireDamage && _lightningDamage > _iceDamage;



        while (!canApplyIgnite && !canApplyChill && !canApplyShock)
        {
            //三个if同时判断大小,可以完成一个随机属性伤害的boss
            if (Random.value < .33f && _fireDamage > 0)//Random.value用于生成一个介于 0.0 和 1.0 之间的随机浮点数
            {
                canApplyIgnite = true;
                _targetStats.ApplyAilments(canApplyIgnite, canApplyChill, canApplyShock);
                //Debug.Log("ignited" );
                return;
            }

            if (Random.value < .5f && _lightningDamage > 0)
            {
                canApplyShock = true;
                _targetStats.ApplyAilments(canApplyIgnite, canApplyChill, canApplyShock);
                //Debug.Log("shocked" );
                return;
            }

            if (Random.value < .99f && _iceDamage > 0)
            {
                canApplyChill = true;
                _targetStats.ApplyAilments(canApplyIgnite, canApplyChill, canApplyShock);
                //Debug.Log("iced" );
                return;
            }
        }

        if (canApplyIgnite)
        {
            _targetStats.SetupIgniteDamage(Mathf.RoundToInt(_fireDamage * .2f));
        }

        if (canApplyShock)
        {
            _targetStats.SetupShockDamage(Mathf.RoundToInt(_lightningDamage * .1f));
        }

        _targetStats.ApplyAilments(canApplyIgnite, canApplyChill, canApplyShock);
    }

    public void ApplyAilments(bool _ignite, bool _chill, bool _shock)//应用异常状态
    {
        bool canApplyIgnite = !isIgnited && !isChilled && !isShocked;
        bool canApplyChill = !isIgnited && !isChilled && !isShocked;
        bool canApplyShock = !isIgnited && !isChilled;//没有其他异常状态才能进入一个异常状态



        //if (isIgnited || isChilled || isShocked)//如果进入一个异常状态就不能进入其他状态了
        //    return;

        if (_ignite && canApplyIgnite)
        {
            isIgnited = _ignite;
            ignitedTimer = ailmentsDuration;

            fx.IgniteFxFor(ailmentsDuration);
        }

        if (_chill && canApplyChill)
        {
            isChilled = _chill;
            chilledTimer = ailmentsDuration;

            float slowPercentage = .2f;//减速百分比

            GetComponent<Entity>().SlowEntityBy(slowPercentage, ailmentsDuration);//减速20%
            fx.ChillFxFor(ailmentsDuration);
        }

        if (_shock && canApplyShock)
        {
            if (!isShocked)
            {
                ApplyShock(_shock);
            }
            else
            {
                if (GetComponent<Player>() != null)//防止敌人打玩家自己被电
                    return;


                HitNearsetTargerWithShockStrike();
            }
        }
    }

    public void ApplyShock(bool _shock)
    {
        if (isShocked)//已经进入感电就不如再次进入
            return;

        isShocked = _shock;
        shockedTimer = ailmentsDuration;

        fx.ShockFxFor(ailmentsDuration);
    }

    private void HitNearsetTargerWithShockStrike()
    {
        Collider2D[] colliders = Physics2D.OverlapCircleAll(transform.position, 25);//碰撞体检测周围的敌人

        float closestDistance = Mathf.Infinity;
        Transform closestEnemy = null;

        foreach (var hit in colliders)
        {
            if (hit.GetComponent<Enemy>() != null && Vector2.Distance(transform.position, hit.transform.position) > 1)//如果是敌人并且不是自己,防止自己被电
            {
                float distanceToEnemy = Vector2.Distance(transform.position, hit.transform.position);

                if (distanceToEnemy < closestDistance)
                {
                    closestDistance = distanceToEnemy;
                    closestEnemy = hit.transform;
                }
            }

            if (closestEnemy == null)
                closestEnemy = transform;


        }


        //寻找最近的敌人然后雷击
        if (closestEnemy != null)
        {
            GameObject newShockStrike = Instantiate(shockStrikePrefab, transform.position, Quaternion.identity);

            newShockStrike.GetComponent<ShockStrike_Controller>().Setup(shockDamage, closestEnemy.GetComponent<CharacterStats>());
        }
    }//闪电攻击附近的目标

    private void ApplyIgniteDamage()
    {
        if (igniteDamageTimer < 0)
        {

            DecreaseHealthBy(igniteDamage);

            //currentHealth -= igniteDamage;

            if (currentHealth < 0 && !isDead)
                Die();

            igniteDamageTimer = igniteDamageCoolDown;
        }
    }
    public void SetupIgniteDamage(int _damage) => igniteDamage = _damage;//设置燃烧伤害

    public void SetupShockDamage(int _damage) => shockDamage = _damage;//设置感电伤害

    #endregion



    public virtual void TakeDamage(int _damage)//造成伤害函数,返回伤害值
    {
        DecreaseHealthBy(_damage);

        GetComponent<Entity>().DamageImpact();
        fx.StartCoroutine("FlashFX");


        Debug.Log(_damage);

        if (currentHealth < 0 && !isDead)
            Die();//人被杀就会死


    }


    public virtual void IncreaseHealthBy(int _amount)//加血函数
    {
        currentHealth += _amount;

        if (currentHealth > GetMaxHealthValue())
            currentHealth = GetMaxHealthValue();

        if (onHealthChanged != null)
            onHealthChanged();
    }


    protected virtual void DecreaseHealthBy(int _damage)//受到伤害的数值变化
    {
        currentHealth -= _damage;

        if (onHealthChanged != null)
            onHealthChanged();
    }




    protected virtual void Die()
    {
        isDead = true;
    }


    #region Stat calculations
    private int CheckTargetResistance(CharacterStats _targetStats, int totalMagicalDamage)//计算魔法伤害(魔抗
    {
        totalMagicalDamage -= _targetStats.magicResistance.GetValue() + (_targetStats.intelligence.GetValue() * 3);//减去魔抗值
        totalMagicalDamage = Mathf.Clamp(totalMagicalDamage, 0, int.MaxValue);//Clamp限制血量数值
        return totalMagicalDamage;
    }

    private int CheckTargetArmor(CharacterStats _targetStats, int totalDamage)//计算物理伤害(护甲
    {
        if (_targetStats.isChilled)
            totalDamage -= Mathf.RoundToInt(_targetStats.armor.GetValue() * .8f);//减去对方的护甲值
        else
            totalDamage -= _targetStats.armor.GetValue();//减去对方的护甲值


        totalDamage = Mathf.Clamp(totalDamage, 0, int.MaxValue);//最小值是0,最大值是int.MaxValue,防止别人打我加血
        return totalDamage;
    }



    private bool TargetCanAvoidAttack(CharacterStats _targetStats)//检测闪避
    {
        int totalEvasion = _targetStats.evasion.GetValue() + _targetStats.agility.GetValue();//总的闪避率

        if (isShocked)
            totalEvasion += 20;

        if (Random.Range(0, 100) < totalEvasion)
        {
            Debug.Log("Attack Avoided");
            return true;
        }

        return false;
    }

    private bool Cancrit()//暴击检测
    {
        int totalCritChance = critChance.GetValue() + agility.GetValue();//总的暴击率

        if (Random.Range(0, 100) < totalCritChance)
        {
            return true;
        }

        return false;

    }

    private int CalculateCriticalDamage(int _damage)//计算爆伤
    {
        float totalCritPower = (critPower.GetValue() + strength.GetValue()) * .01f;
        //Debug.Log("总的暴击率: " + totalCritPower);//total crit power

        float critDamage = _damage * totalCritPower;
        //Debug.Log("取整之后的爆伤" + critDamage);//crit damage before round up

        return Mathf.RoundToInt(critDamage);
    }



    public int GetMaxHealthValue()
    {
        return maxHealth.GetValue() + vitality.GetValue() * 5;
    }//获取最大生命值
    #endregion

    public Stat GetStat(StatType _statType)//根据 buffType 返回需要修改的属性
    {
        if (_statType == StatType.strength) return strength;
        else if (_statType == StatType.agility) return agility;
        else if (_statType == StatType.intelligence) return intelligence;
        else if (_statType == StatType.vitality) return vitality;
        else if (_statType == StatType.damage) return damage;
        else if (_statType == StatType.critChance) return critChance;
        else if (_statType == StatType.critPower) return critPower;
        else if (_statType == StatType.health) return maxHealth;
        else if (_statType == StatType.armor) return armor;
        else if (_statType == StatType.evasion) return evasion;
        else if (_statType == StatType.magicRes) return magicResistance;
        else if (_statType == StatType.fireDamage) return fireDamage;
        else if (_statType == StatType.iceDamage) return iceDamage;
        else if (_statType == StatType.lightingDamage) return lightningDamage;

        else return null;
    }
}

Buff_Effect.cs

using UnityEngine;

//2024年11月11日


[CreateAssetMenu(fileName = "Buff Effect", menuName = "Data/Item effect/Buff effect")]
public class Buff_Effect : ItemEffect
{
    private PlayerStats stats;
    [SerializeField] private StatType buffType;// Buff 的类型
    [SerializeField] private int buffAmount; // Buff 的增加量
    [SerializeField] private float buffDuration;// Buff 持续时间


    public override void ExcuteEffect(Transform _enemyPositon)
    {
        stats = PlayerManager.instance.player.GetComponent<PlayerStats>();//相当于获得了CharacterStats的引用
        stats.IncreaseStatBy(buffAmount, buffDuration, stats.GetStat(buffType));
    }
}

Inventory.cs

更新部分

      [SerializeField] private Transform statSlotParent;
      private UI_StatSlot[] statSlot;

      private void Start()//初始实例化
    {
        inventoryItems = new List<InventoryItem>();
        inventoryDictionary = new Dictionary<ItemData, InventoryItem>();

        stash = new List<InventoryItem>();
        stashDictionary = new Dictionary<ItemData, InventoryItem>();

        equipment = new List<InventoryItem>();
        equipmentDictionary = new Dictionary<ItemData_Equipment, InventoryItem>();


        //同时获取UI中对应的物品槽
        //获得起始的脚本
        inventoryItemSlot = inventorySlotParent.GetComponentsInChildren<UI_ItemSlot>();
        stashItemSlot = stashSlotParent.GetComponentsInChildren<UI_ItemSlot>();
        equipmentSlot = equipmentSlotParent.GetComponentsInChildren<UI_EquipmentSlot>();
        statSlot = statSlotParent.GetComponentsInChildren<UI_StatSlot>();
        AddStartingItems();

    }
using System.Collections.Generic;
using UnityEngine;

//放在创建仓库的empyty对象上,就是仓库的运行函数
public class Inventory : MonoBehaviour
{
    public static Inventory instance;//单例模式

    public List<ItemData> startingItems;//初始装备


    //两种关键的存贮结构
    //List:存储玩家的装备、仓库物品、储藏室物品等
    //Dictionary:存储每个物品的数据以及物品在仓库中的具体信息,例如物品的堆叠数量
    public List<InventoryItem> equipment;
    public Dictionary<ItemData_Equipment, InventoryItem> equipmentDictionary;

    public List<InventoryItem> inventoryItems;
    public Dictionary<ItemData, InventoryItem> inventoryDictionary;

    public List<InventoryItem> stash;
    public Dictionary<ItemData, InventoryItem> stashDictionary;


    //UI物品槽管理:通过以下代码将游戏中的物品槽和UI界面上的物品槽关联起来
    [Header("仓库UI")]//Inventory UI
    [SerializeField] private Transform inventorySlotParent;//位置
    [SerializeField] private Transform stashSlotParent;
    [SerializeField] private Transform equipmentSlotParent;
    [SerializeField] private Transform statSlotParent;


    //物品和材料的存贮位置分开
    
    private UI_ItemSlot[] inventoryItemSlot;
    private UI_ItemSlot[] stashItemSlot;//储藏室
    private UI_EquipmentSlot[] equipmentSlot;//装备
    private UI_StatSlot[] statSlot;


    [Header("物品冷却")]
    private float lastTimeUsedFlask;
    private float lastTimeUsedArmor;


    //P122解决一开始不能用物品的问题,因为一开始冷却被赋值,使用了currentFlask.itemCoolDown
    private float flaskCoolDown;
    private float armorCoolDown;


    private void Awake()
    {
        if (instance == null)
            instance = this;
        else
            Destroy(gameObject);//防止从一个地方到另一个地方
    }


    private void Start()//初始实例化
    {
        inventoryItems = new List<InventoryItem>();
        inventoryDictionary = new Dictionary<ItemData, InventoryItem>();

        stash = new List<InventoryItem>();
        stashDictionary = new Dictionary<ItemData, InventoryItem>();

        equipment = new List<InventoryItem>();
        equipmentDictionary = new Dictionary<ItemData_Equipment, InventoryItem>();


        //同时获取UI中对应的物品槽
        //获得起始的脚本
        inventoryItemSlot = inventorySlotParent.GetComponentsInChildren<UI_ItemSlot>();
        stashItemSlot = stashSlotParent.GetComponentsInChildren<UI_ItemSlot>();
        equipmentSlot = equipmentSlotParent.GetComponentsInChildren<UI_EquipmentSlot>();
        statSlot = statSlotParent.GetComponentsInChildren<UI_StatSlot>();
        AddStartingItems();

    }



    private void AddStartingItems()//添加初始物品
    {
        for (int i = 0; i < startingItems.Count; i++)
        {
            AddItem(startingItems[i]);
        }
    }


    public void EquipItem(ItemData _item)//把一个物品装备到角色身上
    {
        ItemData_Equipment newEquipment = _item as ItemData_Equipment;//把 _item 对象转换为 ItemData_Equipment 类型,表示它是一个装备物品

        InventoryItem newItem = new InventoryItem(newEquipment); //把 ItemData 对象转换为 InventoryItem 对象

        ItemData_Equipment oldEquipment = null;//要删除的物品


        foreach (KeyValuePair<ItemData_Equipment, InventoryItem> item in equipmentDictionary)//遍历装备字典
        {
            if (item.Key.equipmentType == newEquipment.equipmentType)//如果装备类型相同
                oldEquipment = item.Key;//删除该装备
        }


        if (oldEquipment != null)
        {
            UnequipItem(oldEquipment);
            AddItem(oldEquipment);//把要删除的物品放回仓库
        }

        equipment.Add(newItem);
        equipmentDictionary.Add(newEquipment, newItem);
        newEquipment.AddModifiers();//添加装备属性

        RemoveItem(_item);

        UpdataSlotsUI();
    }



    public void UnequipItem(ItemData_Equipment itemToRemove)//移除装备函数
    {
        if (equipmentDictionary.TryGetValue(itemToRemove, out InventoryItem value))
        {

            equipment.Remove(value);
            equipmentDictionary.Remove(itemToRemove);
            itemToRemove.RemoveModifiers();

        }
    }


    private void UpdataSlotsUI()//更新UI物体的数量
    {
        // 更新装备槽
        for (int i = 0; i < equipmentSlot.Length; i++)//将装备物品槽与一个装备字典中的物品进行匹配,并根据匹配结果更新物品槽的内容
        {

            foreach (KeyValuePair<ItemData_Equipment, InventoryItem> item in equipmentDictionary)//遍历装备字典
            {
                if (item.Key.equipmentType == equipmentSlot[i].slotType)//这个条件用于确保物品能放入正确的槽位中
                    equipmentSlot[i].UpdataSlot(item.Value);
            }
        }


        // 清空并更新仓库和储藏室的物品槽
        for (int i = 0; i < inventoryItemSlot.Length; i++)//仓库物品槽
        {
            inventoryItemSlot[i].CleanUpSlot();
        }
        for (int i = 0; i < stashItemSlot.Length; i++)//储藏室中的物品槽
        {
            stashItemSlot[i].CleanUpSlot();
        }


        // 重新填充仓库和储藏室
        for (int i = 0; i < inventoryItems.Count; i++)
        {
            inventoryItemSlot[i].UpdataSlot(inventoryItems[i]);
        }
        for (int i = 0; i < stash.Count; i++)
        {
            stashItemSlot[i].UpdataSlot(stash[i]);
        }

        //更新属性槽
        for (int i = 0; i < statSlot.Length; i++)
        {
            statSlot[i].UpdateStatValueUI();
        }
    }



    public void AddItem(ItemData _item)//据物品类型,将物品添加到仓库(inventory)或者储藏室(stash)
    {
        if (_item.itemType == ItemType.Equipment)
        {
            AddToInventory(_item);
        }
        else if (_item.itemType == ItemType.Material)
        {
            AddToStash(_item);
        }

        UpdataSlotsUI();
    }

    private void AddToStash(ItemData _item)
    {
        if (stashDictionary.TryGetValue(_item, out InventoryItem value))
        {
            value.AddStack();
        }
        else
        {
            InventoryItem newItem = new InventoryItem(_item);
            stash.Add(newItem);
            stashDictionary.Add(_item, newItem);
        }
    }


    private void AddToInventory(ItemData _item)
    {
        if (inventoryDictionary.TryGetValue(_item, out InventoryItem value))//字典中检查仓库中是否有这个物品,具体查找的是ItemData,out InventoryItem value如果找,返回与该键相关联的值
        {
            value.AddStack();//如果物品已经存在于库存中,则增加其堆叠数量
        }
        else
        {
            InventoryItem newItem = new InventoryItem(_item);//如果物品不存在,则创建一个新的 InventoryItem
            inventoryItems.Add(newItem);
            inventoryDictionary.Add(_item, newItem);
        }
    }//检查物品是否已经在仓库里,如果存在则增加堆叠数量,如果不存在则创建新的物品对象并加入仓库

    public void RemoveItem(ItemData _item)
    {
        if (inventoryDictionary.TryGetValue(_item, out InventoryItem value))
        {
            if (value.stackSize <= 1)
            {
                inventoryItems.Remove(value);
                inventoryDictionary.Remove(_item);
            }
            else
            {
                value.RemoveStack();
            }
        }

        if (stashDictionary.TryGetValue(_item, out InventoryItem stashValue))
        {
            if (stashValue.stackSize <= 1)//如果物品的堆叠数量小于等于1,则从库存中删除该物品
            {
                stash.Remove(stashValue);
                stashDictionary.Remove(_item);
            }
            else
            {
                stashValue.RemoveStack();//否则就减少堆寨数量
            }
        }

        UpdataSlotsUI();
    }


    public bool CanCraft(ItemData_Equipment _itemToCraft, List<InventoryItem> _requiredMaterials)//判断是否可以合成的函数
    {
        List<InventoryItem> materialsToRemove = new List<InventoryItem>();

        for (int i = 0; i < _requiredMaterials.Count; i++)
        {
            if (stashDictionary.TryGetValue(_requiredMaterials[i].data, out InventoryItem stashValue))//如果储藏室中没有所需材料
            {
                if (stashValue.stackSize < _requiredMaterials[i].stackSize)//数量是否足够
                {
                    Debug.Log("没有足够的材料");
                    return false;
                }
                else
                {
                    materialsToRemove.Add(stashValue);
                }
            }
            else
            {
                Debug.Log("没有足够的材料");
                return false;
            }
        }

        for (int i = 0; i < materialsToRemove.Count; i++)//使用了就从临时仓库中移除
        {
            RemoveItem(materialsToRemove[i].data);
        }

        AddItem(_itemToCraft);
        Debug.Log("这里是你的物品" + _itemToCraft.name);

        return true;

    }


    public List<InventoryItem> GetEquipmentList() => equipment;//获取装备列表

    public List<InventoryItem> GetStashList() => stash;//获取仓库列表


    public ItemData_Equipment GetEquipment(EquipmentType _type)//获取装备
    {
        ItemData_Equipment equipedItem = null;

        foreach (KeyValuePair<ItemData_Equipment, InventoryItem> item in equipmentDictionary)//遍历装备字典
        {
            if (item.Key.equipmentType == _type)//如果装备类型相同
                equipedItem = item.Key;//删除该装备
        }

        return equipedItem;
    }

    public void UseFlask()//使用药水的函数
    {
        ItemData_Equipment currentFlask = GetEquipment(EquipmentType.Flask);//获取当前的药水

        if (currentFlask == null)
            return;


        bool canUseFlask = Time.time > lastTimeUsedFlask + flaskCoolDown;//判断是否可以使用药水

        if (canUseFlask)
        {
            flaskCoolDown = currentFlask.itemCoolDown;//重置冷却时间,一开始就可以使用物品
            currentFlask.Effect(null);
            lastTimeUsedFlask = Time.time;
        }
        else
            Debug.Log("药水冷却中");
    }

    public bool CanUseArmor()
    {
        ItemData_Equipment currentArmor = GetEquipment(EquipmentType.Armor);//获取当前装备的护甲信息。

        if (Time.time > lastTimeUsedArmor + armorCoolDown)
        {
            //更新冷却时间和使用时间
            armorCoolDown = currentArmor.itemCoolDown;
            lastTimeUsedArmor = Time.time;
            
            return true;
        }

        Debug.Log("护甲正在冷却中");
        return false;

    }

    //private void Updata()
    //{
    //    Debug.Log(Time.time);
    //}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2239366.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【SSL-RL】自监督强化学习:自预测表征 (SPR)算法

&#x1f4e2;本篇文章是博主强化学习&#xff08;RL&#xff09;领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅…

Docker部署kafka集群

1&#xff0c;编写Docker Compose文件 编写一个docker-compose.yml文件来定义服务&#xff0c;以下定义了一个Zookeeper服务和三个Kafka Broker服务&#xff1a; 注意&#xff1a;把10.0.8.4替换成宿主IP version: 3.8services:zookeeper:image: bitnami/zookeeper:latestconta…

Qt滑动条美化自定义

效果展示 主要代码 头文件 下面是hi控件的头文件&#xff0c;我们继承一个Qt原生的滑动条类QSlider&#xff0c;然后在基类的基础上进行自定义&#xff0c;我会对重要的变量进行解析&#xff1a; class XSlider : public QSlider {Q_OBJECT public:explicit XSlider(QWidget…

wordpress实用功能A5资源网同款 隐藏下载框 支付框 需要登录才能查看隐藏的内容

实用功能 隐藏下载框 支付框 需要登录才能查看隐藏的内容, 个人网站防天朝申查实测有效 。 登录前&#xff0c;未登录&#xff1a; 登录后&#xff0c;已登录&#xff1a; 功能说明 该代码段的主要功能是隐藏支付框并为未 登录用户显示一条提示信息&#xff0c;告知他们需要…

Vue 简单入手

前端工程化&#xff08;Front-end Engineering&#xff09;指的是在前端开发中&#xff0c;通过一系列工具、流程和规范的整合&#xff0c;以提高开发效率、代码质量和可维护性的一种技术和实践方法。其核心目的是使得前端开发变得更高效、可扩展和可维护。 文章目录 一、Vue 项…

Spingboot 定时任务与拦截器(详细解释)

在 boot 环境中&#xff0c;一般来说&#xff0c;要实现定时任务&#xff0c;我们有两中方案&#xff0c;一种是使用 Spring 自带的定时 任务处理器 Scheduled 注解&#xff0c;另一种就是使用第三方框架 Quartz &#xff0c; Spring Boot 源自 SpringSpringMVC &#…

无人机+无人车+无人狗+无人船:互通互联技术探索详解

关于“无人机无人车机器狗&#xff08;注&#xff1a;原文中的“无人狗”可能是一个笔误&#xff0c;因为在实际技术领域中&#xff0c;常用的是“机器狗”这一术语&#xff09;无人船”的互通互联技术&#xff0c;以下是对其的详细探索与解析&#xff1a; 一、系统架构与关键…

ima.copilot-腾讯智能工作台

一、产品描述 ima.copilot是腾讯推出的基于腾讯混元大模型技术的智能工作台&#xff0c;通过先进的人工智能技术&#xff0c;为用户提供了一个全新的搜读写体验&#xff0c;让知识管理变得更加智能和高效。它不仅是一个工具&#xff0c;更是一个智能的伙伴&#xff0c;能够帮助…

集合卡尔曼滤波(EnsembleKalmanFilter)的MATLAB例程(三维、二维)

本 M A T L A B MATLAB MATLAB代码实现了一个三维动态系统的集合卡尔曼滤波&#xff08;Ensemble Kalman Filter, EnKF&#xff09;示例。代码的主要目的是通过模拟真实状态和测量值&#xff0c;使用 EnKF 方法对动态系统状态进行估计。 文章目录 参数设置初始化真实状态定义状…

【动手学电机驱动】STM32-FOC(5)基于 IHM03 的无感 FOC 控制

STM32-FOC&#xff08;1&#xff09;STM32 电机控制的软件开发环境 STM32-FOC&#xff08;2&#xff09;STM32 导入和创建项目 STM32-FOC&#xff08;3&#xff09;STM32 三路互补 PWM 输出 STM32-FOC&#xff08;4&#xff09;IHM03 电机控制套件介绍 STM32-FOC&#xff08;5&…

光老化测试的三种试验:紫外老化、氙灯老化、碳弧灯老化

光老化是指材料在阳光照射下&#xff0c;由于紫外线、热和氧气的共同作用而发生的物理和化学变化。这种现象对纺织材料、塑料材料、涂料材料和橡胶材料的应用有显著影响。这些材料户外家具、汽车内饰和户外供水排水管道、建筑外墙涂料、汽车漆面、船舶涂料、汽车轮胎、密封件、…

VMWare安装包及安装过程

虚拟机基本使用 检查自己是否开启虚拟化 如果虚拟化没有开启&#xff0c;需要自行开启&#xff1a;百度加上自己电脑的品牌型号&#xff0c;进入BIOS界面开启 什么是虚拟机 所谓的虚拟机&#xff0c;就是在当前计算机系统中&#xff0c;又开启了一个虚拟系统 这个虚拟系统&…

消费的外部性

大学宿舍&#xff0c;遇到在你睡觉的时候开外放不戴耳机的室友&#xff0c;但中午12点&#xff0c;室友却在那拉上窗帘睡觉。能带饭吗&#xff1f;能代签到吗&#xff1f;能倒个垃圾吗&#xff1f;能带个外卖吗&#xff1f;自己永远麻烦别人&#xff0c;你要让他帮个忙又这推那…

易趋亮相2024 PMI项目管理大会

11月9日-10日&#xff0c;2024 PMI项目管理大会在广州圆满举办&#xff0c;项目管理行业优秀代表企业——易趋&#xff08;隶属深圳市蓝云软件有限公司&#xff09;&#xff0c;携最新产品和解决方案亮相本次展会。 (主论坛现场&#xff09; 本届大会以“‘项’有所成 行以致远…

边缘计算与推理算力:智能时代的加速引擎

在数据量爆炸性增长的今天&#xff0c;边缘计算与推理算力正成为推动智能应用的关键力量。智能家居、自动驾驶、工业4.0等领域正在逐步从传统的云端计算转向边缘计算&#xff0c;而推理算力的加入&#xff0c;为边缘计算提供了更强的数据处理能力和实时决策能力。本文将探讨边缘…

基于matlab的CNN食物识别分类系统,matlab深度学习分类,训练+数据集+界面

文章目录 前言&#x1f393;一、数据集准备&#x1f393;二、模型训练&#x1f340;&#x1f340;1.初始化&#x1f340;&#x1f340;2.加载数据集&#x1f340;&#x1f340;3.划分数据集&#xff0c;并保存到新的文件夹&#x1f340;&#x1f340;4.可视化数据集&#x1f34…

马斯克万卡集群AI数据中心引发的科技涟漪:智算数据中心挑战与机遇的全景洞察

一、AI 爆发重塑数据中心格局 随着AI 技术的迅猛发展&#xff0c;尤其是大模型的崛起&#xff0c;其对数据中心产生了极为深远的影响。大模型以其数以亿计甚至更多的参数和对海量数据的处理需求&#xff0c;成为了 AI 发展的核心驱动力之一&#xff0c;同时也为数据中心带来了…

移远通信亮相骁龙AI PC生态科技日,以领先的5G及Wi-Fi产品革新PC用户体验

PC作为人们学习、办公、娱乐的重要工具&#xff0c;已经深度融入我们的工作和生活。随着物联网技术的快速发展&#xff0c;以及人们对PC性能要求的逐步提高&#xff0c;AI PC成为了行业发展的重要趋势。 11月7-8日&#xff0c;骁龙AI PC生态科技日在深圳举办。作为高通骁龙的重…

Unity资源打包Addressable资源保存在项目中

怎么打包先看“Unity资源打包Addressable AA包” 其中遗留一个问题&#xff0c;下载下来的资源被保存在C盘中了&#xff0c;可不可以保存在项目中呢&#xff1f;可以。 新建了一个项目&#xff0c;路径与“Unity资源打包Addressable AA包”都不相同了 1.创建资源缓存路径 在…

postman变量和脚本功能介绍

1、基本概念——global、collection、environment 在postman中&#xff0c;为了更好的管理各类变量、测试环境以及脚本等&#xff0c;创建了一些概念&#xff0c;包括&#xff1a;globals、collection、environment。其实在postman中&#xff0c;最上层还有一个Workspaces的概…