Bootstrap

Unity类银河战士恶魔城学习总结(P145 Save Skill Tree 保存技能树)

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

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

本章节实现了技能树的保存

警告!!!

如果有LoadData()和SaveData()无法使用的问题

SaveManager中的FindAllSaveManagers()加上true

或者把SaveManager.cs放到最前面

这个在编辑/项目设置/脚本执行顺序里面

UI_SkillTreeSlot.cs

using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;


//2024年11月17日
public class UI_SkillTreeSlot : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler,ISaveManager
{
    private UI ui;
    private Image skillImage;//当前技能槽的图片组件

    [SerializeField] private int skillCost;//技能价格
    [SerializeField] private string skillName;
    [TextArea]
    [SerializeField] private string skillDescription;
    [SerializeField] private Color lockedSkillColor;//技能未解锁时的颜色


    public bool unlocked;

    [SerializeField] private UI_SkillTreeSlot[] shouldBeUnlocked;//解锁前置条件
    [SerializeField] private UI_SkillTreeSlot[] shouldBeLocked;//锁定条件



    private void OnValidate()
    {
        gameObject.name = "SkillTreeSlot_UI - " + skillName;
    }

    private void Awake()
    {
        GetComponent<Button>().onClick.AddListener(() => UnlockSkillSlot());//给 Button 组件绑定点击事件,用于触发技能槽解锁逻辑
    }

    private void Start()
    {
        skillImage = GetComponent<Image>();
        ui = GetComponentInParent<UI>();

        skillImage.color = lockedSkillColor;//设置初始颜色为锁定颜色


        if(unlocked)
            skillImage.color = Color.white;
    }


    public void UnlockSkillSlot()//解锁技能
    {
        if(unlocked)//防止一直扣钱,2024.11.22我自己加的
            return;

        if (PlayerManager.instance.HaveEnoughMoney(skillCost) == false)//检查是否有足够的钱
            return;


        for (int i = 0; i < shouldBeUnlocked.Length; i++)//前置解锁检查
        {
            if (shouldBeUnlocked[i].unlocked == false)
            {
                Debug.Log("不能解锁技能");
                return;
            }
        }


        for (int i = 0; i < shouldBeLocked.Length; i++)//锁定检查
        {
            if (shouldBeLocked[i].unlocked == true)
            {
                Debug.Log("不能解锁技能");
                return;
            }
        }

        unlocked = true;
        skillImage.color = Color.white;
    }


    public void OnPointerEnter(PointerEventData eventData)
    {
        ui.skillToolTip.ShowToolTip(skillDescription, skillName, skillCost);
    }

    public void OnPointerExit(PointerEventData eventData)
    {
        ui.skillToolTip.HideToolTip();//鼠标离开槽位时,隐藏技能描述提示框
    }


    public void LoadData(GameData _data)
    {
        if(_data.skillTree.TryGetValue(skillName, out bool value))
        {
            unlocked = value;
            
        }
    }

    public void SaveData(ref GameData _data)
    {
        if (_data.skillTree.TryGetValue(skillName, out bool value))
        {
            _data.skillTree.Remove(skillName);
            _data.skillTree.Add(skillName, unlocked);

        }
        else
            _data.skillTree.Add(skillName, unlocked);

    }

}

Skill.cs

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

public class Skill : MonoBehaviour
{
    public float cooldown;
    protected float cooldownTimer;

    protected Player player;

    protected virtual void Start()
    {
        player = PlayerManager.instance.player;

        CheckUnlock();
    }

    protected virtual void Update()
    {
        cooldownTimer -= Time.deltaTime;
    }

    protected virtual void CheckUnlock()
    {

    }


    public virtual bool CanUseSkill()
    {
        if (cooldownTimer < 0)
        {
            UseSkill();
            cooldownTimer = cooldown;
            return true;
        }
        else
        {
            Debug.Log("Skill is on cooldown");
            return false;
        }
    }

    public virtual void UseSkill()
    {
        //放技能
    }

    protected virtual Transform FindClosesetEnemy(Transform _checkTransform)//寻找附近的敌人,返回最近的敌人
    {

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

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

        foreach (var hit in colliders)
        {
            if (hit.GetComponent<Enemy>() != null)
            {
                float distanceToEnemy = Vector2.Distance(_checkTransform.position, hit.transform.position);

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

        return closestEnemy;
    }

}

Clone_Skill.cs

以下都是一些简单的覆盖

    protected override void CheckUnlock()
    {
        UnlockCloneAttack();
        UnlockAggressiveClone();
        UnlockMultipleClone();
        UnlockCryStalInstead();
    }

 Dodge_Skill.cs

    protected override void CheckUnlock()
    {
        UnlockDodge();
        UnlockMirageDodge();
    }

Blackhole_Skill.cs

    protected override void CheckUnlock()
    {
        base.CheckUnlock();

        UnlockBlackHole();  
    }

Crystal_Skill.cs

    protected override void CheckUnlock()
    {
        UnlockCrystal();
        UnlockCrystalMirage();
        UnlockExplosiveCrystal();
        UnlockMovingCrystal();
        UnlockMultiStackCrystal();
    }

Dash_Skill.cs

    override protected void CheckUnlock()
    {
        UnlockDash();
        UnlockCloneOnDash();
        UnlockCloneOnArrival();
    }

Parry_SKill.cs

    protected override void CheckUnlock()
    {
        UnlockParry();
        UnlockParryRestor();
        UnlockParrtWithMirage();
    }

Sword_Skill.cs

    protected override void CheckUnlock()
    {
        UnlockSword();
        UnlockBounceSword();
        UnlockPierceSword();
        UnlockSpinSword();
        UnlockTimeStop();
        UnlockVolnurable();
    }

;