【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili
教程源地址:https://www.udemy.com/course/2d-rpg-alexdev/
完成了技能树上的格挡技能的UI逻辑
Parry_SKill.cs
核心功能
代码主要围绕以下功能展开:
(1)技能解锁
- 通过绑定解锁按钮的点击事件(
onClick
),来解锁技能。 - 每个技能都依赖一个
UI_SKillTreeSlot
(可能是一个技能树的 UI 元素),通过检测其unlocked
属性判断技能是否解锁成功。
(2)技能效果
a. 使用技能 (UseSkill
)
- 在技能使用时,检查特定效果是否已解锁,并执行对应功能。
- 恢复生命值的功能:
b. 格挡幻影 (MakeMirageOnParry
)
- 如果
parrtWithMirageUnlocked
解锁,生成一个幻影(类似分身):
UI逻辑:
UI_SKillTreeSlot
是解锁按钮的一个组件,应该包括:
- 一个布尔变量
unlocked
表示当前技能是否解锁。 - 一个
Button
组件用作解锁触发点。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Parry_SKill : Skill
{
[Header("反击")]//parry
[SerializeField] private UI_SKillTreeSlot parryUnlockButton;
public bool parryUnlocked{ get; private set; }
[Header("反击恢复")]//Parry restor
[SerializeField] private UI_SKillTreeSlot restorUnlockButton;
[Range(0f,1f)]
[SerializeField] private float restoreHealthPercentage;
public bool restorUnlocked{ get; private set; }
[Header("格挡幻影")]//Parry mirrage
[SerializeField] private UI_SKillTreeSlot parrtWithMirageUnlockButton;
public bool parrtWithMirageUnlocked { get; private set; }
public override void UseSkill()
{
base.UseSkill();
if(restorUnlocked)
{
int restoreAmount = Mathf.RoundToInt(player.stats.GetMaxHealthValue() * restoreHealthPercentage);
player.stats.IncreaseHealthBy(restoreAmount);
}
}
protected override void Start()
{
base.Start();
parryUnlockButton.GetComponent<Button>().onClick.AddListener(UnlockParry);
restorUnlockButton.GetComponent<Button>().onClick.AddListener(UnlockParryRestor);
parrtWithMirageUnlockButton.GetComponent<Button>().onClick.AddListener(UnlockParrtWithMirage);
}
private void UnlockParry()
{
if (parryUnlockButton.unlocked)
parryUnlocked = true;
}
private void UnlockParryRestor()
{
if (restorUnlockButton.unlocked)
restorUnlocked = true;
}
private void UnlockParrtWithMirage()
{
if (parrtWithMirageUnlockButton.unlocked)
parrtWithMirageUnlocked = true;
}
public void MakeMirageOnParry(Transform _respawnTransform)
{
if (parrtWithMirageUnlocked)
SkillManager.instance.clone.CreateCloneWithDelay(_respawnTransform);
}
}
PlayerGroundedState.cs
修改了格挡技能Q的逻辑判断
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerGroundedState : PlayerState
{
public PlayerGroundedState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
{
}
public override void Enter()
{
base.Enter();
}
public override void Exit()
{
base.Exit();
}
public override void Update()
{
base.Update();
if (Input.GetKeyDown(KeyCode.R))
stateMachine.ChangeState(player.blackHole);
if (Input.GetKeyDown(KeyCode.Mouse1) && HasNoSword())
stateMachine.ChangeState(player.aimSword);
if (Input.GetKeyDown(KeyCode.Q) && player.skill.parry.parryUnlocked)
stateMachine.ChangeState(player.counterAttack);
if (Input.GetKeyDown(KeyCode.Mouse0))//GetKeyDown改成GetKey按住就可以攻击了
stateMachine.ChangeState(player.primaryAttack);
if (!player.IsGroundDetected())
stateMachine.ChangeState(player.airState);
if (Input.GetKeyDown(KeyCode.Space) && player.IsGroundDetected())
stateMachine.ChangeState(player.jumpState);
}
private bool HasNoSword()
{
if (!player.sword)
{
return true;
}
player.sword.GetComponent<Sword_Skill_Controller>().ReturnSword();
return false;
}
}
PlayerCounterAttackState.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCounterAttackState : PlayerState
{
private bool canCreateClone;
public PlayerCounterAttackState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
{
}
public override void Enter()
{
base.Enter();
canCreateClone = true;
stateTimer = player.counterAttackDuration;
player.anim.SetBool("SuccessfulCounterAttack", false);
}
public override void Exit()
{
base.Exit();
}
public override void Update()
{
base.Update();
player.SetZeroVelocity();
Collider2D[] colliders = Physics2D.OverlapCircleAll(player.attackCheck.position, player.attackCheckRadius);//这行代码在 Unity 中用于检测一个圆形区域内的所有碰撞体,并返回它们的数组。
foreach (var hit in colliders)//foreach循环是一个迭代器,它可以遍历数组、集合、列表、字典等数据结构。攻击到敌人后,调用伤害函数
{
if (hit.GetComponent<Enemy>() != null)
{
if (hit.GetComponent<Enemy>().CanBeStunned())
{
stateTimer = 10;//大于1的数,保证不会进入idle状态
player.anim.SetBool("SuccessfulCounterAttack", true);
player.skill.parry.UseSkill();
if (canCreateClone)
{
canCreateClone = false;
player.skill.parry.MakeMirageOnParry(hit.transform);
}
}
}
}
if (stateTimer < 0 || triggerCalled)
stateMachine.ChangeState(player.idleState);
}
}
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")]
[SerializeField] private UI_SKillTreeSlot dashUnlockButton;
public bool dashUnlocked { get; private set; }
[Header("Clone on dash")]
[SerializeField] private UI_SKillTreeSlot cloneOnDashUnlockButton;
public bool cloneOmDashUnlocked { get; private set; }
[Header("Clone on arrival")]
[SerializeField] private UI_SKillTreeSlot cloneOnArrivalUnlockButton;
public bool cloneOnArrivalUnlocked { get; private set; }
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);
}
}