Unity类银河战士恶魔城学习总结(P132 Merge skill tree with skill Manager 把技能树和冲刺技能相组合)
【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili
教程源地址:https://www.udemy.com/course/2d-rpg-alexdev/
本章节实现了解锁技能后才可以使用技能,先完成了冲刺技能的锁定解锁
Dash_Skill.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
//2024年11月19日添加解锁技能逻辑
public class Dash_Skill : Skill
{
[Header("Dash")]
public bool dashUnlocked;
[SerializeField] private UI_SKillTreeSlot dashUnlockButton;
[Header("Clone on dash")]
public bool cloneOmDashUnlocked;
[SerializeField] private UI_SKillTreeSlot cloneOnDashUnlockButton;
[Header("Clone on arrival")]
public bool cloneOnArrivalUnlocked;
[SerializeField] private UI_SKillTreeSlot cloneOnArrivalUnlockButton;
public override void UseSkill()
{
base.UseSkill();
}
protected override void Start()
{
base.Start();
dashUnlockButton.GetComponent<Button>().onClick.AddListener(UnlockDash);
cloneOnDashUnlockButton.GetComponent<Button>().onClick.AddListener(UnlockCloneOnDash);
cloneOnArrivalUnlockButton.GetComponent<Button>().onClick.AddListener(UnlockCloneOnArrival);
}
private void UnlockDash()
{
if (dashUnlockButton.unlocked)
dashUnlocked = true;
}
private void UnlockCloneOnDash()
{
if (cloneOnDashUnlockButton.unlocked)
cloneOmDashUnlocked = true;
}
private void UnlockCloneOnArrival()
{
if (cloneOnArrivalUnlockButton.unlocked)
cloneOnArrivalUnlocked = true;
}
public void CloneOnDash()
{
if (cloneOmDashUnlocked)
SkillManager.instance.clone.CreateClone(player.transform, Vector3.zero);
}
public void CloneOnArrival()
{
if (cloneOnArrivalUnlocked)
SkillManager.instance.clone.CreateClone(player.transform, Vector3.zero);
}
}
UI_SKillTreeSlot .cs
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
//2024年11月17日
public class UI_SKillTreeSlot : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
private UI ui;
private Image skillImage;//当前技能槽的图片组件
[SerializeField] private int skillPirce;//技能价格
[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;//设置初始颜色为锁定颜色
}
public void UnlockSkillSlot()
{
if(PlayerManager.instance.HaveEnoughMoney(skillPirce) == 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);
Vector2 mousePosition = Input.mousePosition;
float xOffset = 0;
float yOffset = 0;
if (mousePosition.x > 600)
xOffset = -150;
else
xOffset = 150;//鼠标靠近屏幕右侧时,提示框向左偏移;否则向右偏移
if (mousePosition.y > 320)
yOffset = -150;
else
yOffset = 150;//鼠标靠近屏幕顶部时,提示框向下偏移;否则向上偏移
ui.skillToolTip.transform.position = new Vector2(mousePosition.x + xOffset, mousePosition.y + yOffset);//更新提示框位置为鼠标位置偏移后的点
}
public void OnPointerExit(PointerEventData eventData)
{
ui.skillToolTip.HideToolTip();//鼠标离开槽位时,隐藏技能描述提示框
}
}
PlayerManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//P63,制作玩家管理器和技能管理器
//可以在SkeletonBattleState中通过PlayerManager.instance.player.transform获取到玩家的位置
public class PlayerManager : MonoBehaviour
{
//全局访问
public static PlayerManager instance;//单例模式
public Player player;
public int currency;
private void Awake()
{
if (instance != null)
Destroy(instance.gameObject);
else
instance = this;
}
public bool HaveEnoughMoney(int _price)//是否有钱去买技能
{
if (_price > currency)
{
Debug.Log("没有足够的钱");
return false;
}
else
currency -= _price;
return true;
}
}
Clone_Skill.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Clone_Skill : Skill
{
[Header("Clone Info")]
[SerializeField] private GameObject clonePrefab;//克隆原型
[SerializeField] private float cloneDuration;//克隆持续时间
[SerializeField] private bool canAttack;// 判断是否可以攻击
[SerializeField] private bool canCreateCloneOnCounterAttack;
[Header("Clone can Duplicate")]
[SerializeField] private bool canDuplicateClone;//可以重复clone
[SerializeField] private float chanceToDuplicate;//重复clone的几率
[Header("Crystal instead of clone")]
public bool crystalInsteadOfClone;//是否使用水晶代替克隆
public void CreateClone(Transform _clonePosition,Vector3 _offset)//传入克隆位置
{
if(crystalInsteadOfClone)//克隆转换成水晶
{
SkillManager.instance.crystal.CreateCrystal();
SkillManager.instance.crystal.CurrentCrystalChooseRandomTarget();
return;
}
GameObject newClone = Instantiate(clonePrefab);//创建新的克隆//克隆 original 对象并返回克隆对象。
newClone.GetComponent<Clone_Skill_Controller>().
SetupClone(_clonePosition, cloneDuration, canAttack,_offset,FindClosesetEnemy(newClone.transform),canDuplicateClone, chanceToDuplicate,player);
}
public void CreateCloneOnCounterAttack(Transform _enemyTransform)
{
if(canCreateCloneOnCounterAttack)
StartCoroutine(CreateCloneWithDelay(_enemyTransform, new Vector3(2 * player.facingDir, 0)));
}
private IEnumerator CreateCloneWithDelay(Transform _transform,Vector3 _offset)
{
yield return new WaitForSeconds(.4f);
CreateClone(_transform, _offset);
}
}