实现技能释放与技能切换功能,做一个居合斩技能
实现技能管理类SkillManager管理方向键注册的技能以及切换当前选中技能
实现Skill类,包含释放技能需要满足的条件以及技能开始,执行,结束过程的逻辑
实现技能释放状态,在状态中执行当前选中技能的逻辑
实现技能管理类SkillManager 在场景中添加一个空物体,挂载SkillManager脚本。SkillManager是单例,所有类都访问同一个对象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 public class PlayerSkillManager : MonoBehaviour { public static PlayerSkillManager instance; public bool canChangeSkill = true ; public Player player; public Skill upSkill; public Skill downSkill; public Skill leftSkill; public Skill rightSkill; public Skill currentSkill; void Awake () { if (instance != null ) Destroy(instance.gameObject); else instance = this ; upSkill = new LightCut(); downSkill = new ShiledCast(); leftSkill = new HolySlash(); } void Start () { player.playerInput.GamePlay.ChangeSkill.performed += OnDPadPerformed; } private void OnDPadPerformed (UnityEngine.InputSystem.InputAction.CallbackContext context ) { if (!canChangeSkill) return ; Vector2 dpad = context.ReadValue<Vector2>(); if (dpad == Vector2.zero) return ; if (dpad.y > 0.5f ) currentSkill = upSkill; else if (dpad.y < -0.5f ) currentSkill = downSkill; else if (dpad.x < -0.5f ) currentSkill = leftSkill; else if (dpad.x > 0.5f ) currentSkill = rightSkill; Debug.Log("当前技能切换为: " + currentSkill.skillName); } void OnDestroy () { player.playerInput.GamePlay.ChangeSkill.performed -= OnDPadPerformed; } }
实现Skill类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 public class Skill { public string skillName; public bool skillFinished = false ; public bool skillTrigger = false ; public virtual bool IsSkillAvailable () { return true ; } public virtual void ReleaseSkill () { Debug.Log("Releasing skill: " + skillName); skillFinished = false ; } public virtual void SkillReleaseOver () { Debug.Log("Finish skill: " + skillName); } public virtual void UseSkill () { Debug.Log("Using skill: " + skillName); } public virtual void Update () { } public virtual void FixedUpdate () { } }
实现技能释放逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 public virtual void Enter (){ rigidBody = player.rigidBody; animator = player.animator; playerInput = player.playerInput; physicsCheck = player.physicsCheck; animFinTrigger = false ; inputXY = playerInput.GamePlay.Move.ReadValue<Vector2>(); if (!string .IsNullOrEmpty(animBoolName) && HasAnimatorParameter(animator, animBoolName, AnimatorControllerParameterType.Bool)) animator.SetBool(animBoolName, true ); if (!string .IsNullOrEmpty(animTriggerName) && HasAnimatorParameter(animator, animTriggerName, AnimatorControllerParameterType.Trigger)) animator.SetTrigger(animTriggerName); player.playerInput.GamePlay.ReleaseSkill.started += ReleaseSkill; } private void ReleaseSkill (InputAction.CallbackContext context ){ if (PlayerSkillManager.instance.currentSkill != null && PlayerSkillManager.instance.currentSkill.IsSkillAvailable()) player.stateMachine.ChangeState(player.realseSkillState); else Debug.Log("Current skill is not available or null" ); }
实现技能释放状态 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 public class PlayerRealseSkillState : PlayerState { private Skill currentSkill; public PlayerRealseSkillState (Player player, PlayerStateMachine stateMachine, string animBoolName, string animTriggerName ) : base (player, stateMachine, animBoolName, animTriggerName ) { } public override void Enter () { base .Enter(); PlayerSkillManager.instance.canChangeSkill = false ; currentSkill = PlayerSkillManager.instance.currentSkill; currentSkill.ReleaseSkill(); } public override void Exit () { base .Exit(); currentSkill.SkillReleaseOver(); PlayerSkillManager.instance.canChangeSkill = true ; } public override void LogicUpdate () { base .LogicUpdate(); if (currentSkill.skillFinished) stateMachine.ChangeState(player.idleState); } public override void PhysicsUpdate () { currentSkill.FixedUpdate(); } }
实现LightCut技能
LightCut分为四段:收刀入鞘,蓄力,冲刺斩击,结束后摇
收刀状态为前摇动画,不能取消
蓄力过程需要玩家按住右扳机
玩家松开扳机就向前冲刺,对冲刺中碰到的敌人造成伤害
LightCut类 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 public class LightCut : Skill{ public override bool IsSkillAvailable () { if (PlayerManager.instance.player.physicsCheck.isGrounded && PlayerSkillManager.instance.canChangeSkill) return true ; else return false ; } public override void ReleaseSkill () { base.ReleaseSkill (); PlayerManager.instance.player.animator.SetTrigger ("LightCut" ); PlayerManager.instance.player.playerInput.GamePlay.ReleaseSkill.canceled += Dash; } public override void SkillReleaseOver () { Debug.Log ("Finish skill: " + skillName); PlayerManager.instance.player.playerInput.GamePlay.ReleaseSkill.canceled -= Dash; } private void Dash (InputAction.CallbackContext context) { PlayerManager.instance.player.animator.SetTrigger ("LightCutRelease" ); } public override void Update () { } public override void FixedUpdate () { if (skillTrigger) PlayerManager.instance.player.SetVelocity (2 * PlayerManager.instance.player.facingDir * PlayerManager.instance.player.dashSpeed, 0 ); else PlayerManager.instance.player.SetZeroVelocity (); } }
Animator状态机设置
蓄力&&冲刺斩击的实现
按下扳机,进入技能释放状态,Enter调用技能的ReleaseSkill函数,触发ToLightCut动画,也就是收刀前摇
在State中注册扳机键的canceled事件,当松开按键就触发Dash,播放LightCut动画,否则循环播放蓄力动画
给冲刺斩击的动画注册动画事件,控制skillTrigger,实现斩击过程中的冲刺
1 2 3 4 5 6 7 8 9 10 11 public void AnimationSkillTrigger (){ PlayerSkillManager.instance.currentSkill.skillTrigger = true ; } public void AnimationSkillTriggerFalse (){ PlayerSkillManager.instance.currentSkill.skillTrigger = false ; }