p=61 Player’s Counter attack (完整弹反功能) ;类恶魔城Demo学习

Player’s Counter attack (完整弹反功能)

接着继续制作玩家弹反部分,包括了动画、输入
动画新加1格挡、2成功格挡

思路:

	敌人(Skeleton)已经做了在动画之间开启窗口和关闭窗口。
	玩家在按下格挡后检测前方敌人是否处于窗口(CanBeStuned)且
因为public所以player也可访问enemy这个方法。
	是就玩家格挡成功转向格挡成功动画(运行完后trgger=true跳回idle)且
同时敌人被调用CanBeStuned跳到Stun状态。
注:

在实现前先去注释掉Enemy_Skeleton的这里(否则按Q就触发Stun)

后面去PlayerState 检测输入

//if (Input.GetKeyDown(KeyCode.U))
//{
//    stateMachine.ChangeState(stunState);
//}
Player脚本的代码,主要是声明和new新的状态
using System.Collections;
using System.Collections.Generic;
using System.Linq.Expressions;
using UnityEngine;

public class Player : Entity
{
    [Header("Move Info")]
    public float moveSpeed = 8f;
    public float jumpForce = 10f;


    [Header("Dash Info")]
    public float dashSpeed =20f;
    public float dashDuration;
    public float dashCoolDown;    //CD
    public float dashUsageTime;



    [Header("Attack Info")]
    public Vector2[] attackMovement;  //双值数组

    [Header("CounterAttack Info")]
    public float counterAttackDuration;

    #region States
    public PlayerStateMachine stateMachine {  get; private set; }
    public PlayerIdleState idleState { get; private set; }
    public PlayerMoveState moveState { get; private set; }
    public PlayerJumpState jumpState { get; private set; }
    public PlayerFallState fallState { get; private set; }
    public PlayerDashState dashState { get; private set; }
    public PlayerWallSlideState wallSlideState { get; private set; }
    public PlayerWallJumpState wallJump { get; private set; }
    public PlayerPrimaryAttackState primaryAttack { get; private set; }
    public PlayerCounterAttack counterAttack {  get; private set; }
    #endregion


    protected override void Awake()
    {
        stateMachine = new PlayerStateMachine();

        idleState = new PlayerIdleState(this, stateMachine,"Idle");
        moveState = new PlayerMoveState(this, stateMachine, "Move");
        jumpState = new PlayerJumpState(this, stateMachine, "Jump");
        fallState = new PlayerFallState(this, stateMachine, "Fall");
        dashState = new PlayerDashState(this, stateMachine, "Dash");
        wallSlideState = new PlayerWallSlideState(this, stateMachine, "WallSlide");
        wallJump = new PlayerWallJumpState(this, stateMachine, "Jump");
        primaryAttack = new PlayerPrimaryAttackState(this, stateMachine, "Attack");
        counterAttack = new PlayerCounterAttack(this, stateMachine, "CounterAttack");


    }

    protected override void Start()
    {
        //Debug.Log("开始");
        base.Start();
        stateMachine.Initialize(idleState);
    }

    protected override void Update()
    {
        base.Update();
        stateMachine.currentState.Update();
        CheckForDashInput();
        //Test();
    }

    //========================================================================================================================
    public void Test()
    {
        //Debug.Log("Wall" + IsWallSlideDetect());
        //Debug.Log("Ground" + IsGroundDetect());
    }

    public override void Damage()
    {
        base.Damage();
    }

    public void AnimationTrigger() => stateMachine.currentState.AnimationFinishTrigger();
    //可以让其他函数不调用状态机就调用玩家组建里面的方法,不然不好确认是哪个stateMachine(不同玩家的)
    //方法意思:这个状态机的当前状态将执行trigger

    
    public void CheckForDashInput() 
    {
        dashUsageTime -= Time.deltaTime;
        if (IsGroundDetect()) 
        {
            return;
        }
        if (Input.GetKeyDown(KeyCode.LeftShift ) && dashUsageTime < 0)
        {
            dashUsageTime = dashCoolDown;   //重置cd
            dashDir = Input.GetAxisRaw("Horizontal");
            if(dashDir == 0)
            {
                dashDir = facingDir;
            }
            stateMachine.ChangeState(dashState);
        }
    }

    
    
}

PlayerCounterAttack 的代码(本节重点),新增主要是检测敌人是否处于弹反窗口且敌人转向Stun(如果是true)

注:在这里插入图片描述
SuccessFul动画最后一帧要加入trigger,使得运行完后CounterAttack脚本转向Idle。通过最下面if

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;

public class PlayerCounterAttack : PlayerState
{
    public PlayerCounterAttack(Player _player, PlayerStateMachine _stateMachine, string _animBoolName) : base(_player, _stateMachine, _animBoolName)
    {
    }

    public override void Enter()
    {
        base.Enter();
        //格挡时间
        stateTimer = player.counterAttackDuration;
        //成功格挡动画为false
        player.anim.SetBool("SuccessfulCountAttack", false);
    }
    public override void Update()
    {
        base.Update();
        //一个圆的碰撞体  (数组)
        Collider2D[] colliders = Physics2D.OverlapCircleAll(player.attackCheck.position, player.attackCheckRadius);

        foreach (var hit in colliders)
        {
            if (hit.GetComponent<Enemy>() != null)
            {
                if(hit.GetComponent<Enemy>().CanBeStuned())
                {
                    player.anim.SetBool("SuccessfulCountAttack", true);
                    stateTimer = 10;   //重置时间,让不退出
                    Debug.Log("弹反!");
                }
                
            }

        }
        Debug.Log("triggerCalled= " + triggerCalled);
        Debug.Log("Timer= " + stateTimer);
        //时间到,弹反失败
        if (stateTimer < 0 || triggerCalled)
        {
            
            player.stateMachine.ChangeState(player.idleState);
        }
    }

    public override void Exit()
    {
        base.Exit();
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值