Unity 人物连招(三段连击)

一: 连招思路

首先人物角色上有三个攻击实例对象 Damage,每一个damage定义了攻击的伤害值,攻击距离,触发器名称,伤害的发起者,攻击持续时间,攻击重置时间,伤害的碰撞框大小等字段:

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

[System.Serializable]
public class Damage
{
    /// <summary>
    /// 触发动画触发器名称
    /// </summary>
    public string animationTrigger = "";
    /// <summary>
    /// 组合攻击伤害
    /// </summary>
    public int damage = 0;

    /// <summary>
    /// 伤害的攻击者
    /// </summary>
    public GameObject inflictor;
    /// <summary>
    /// 组合攻击持续时间
    /// </summary>
    public float duration = 1f;
    /// <summary>
    /// 连击重置时间 超过这个时间如果没有收到连击序列 连击将会被取消
    /// </summary>
    public float comboResetTime = .5f;

    [Space(10)]
    [Header("hit collider settings")]
    public float collSize;
    public float collDistance;

    public float collHeight;

}

当按下某一个键位的时候,播放对应索引的攻击,如果在攻击时间后再次收到了攻击键位的按下就认为是连击状态,这时候继续播放攻击动作。

二: 代码实现

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

public class PlayerCombat : MonoBehaviour
{
    // 主角的攻击组合
    public Damage[] attackCombo;
    // 主角的最后一次攻击类型
    public Damage lastAttack;
    // 记录最后一次攻击时间
    public float lastAttackTime;

    public PlayerController playerController;
    public CharactorState charactorState;
    // 最近一次攻击的索引
    public int attackIndex = 0;
    // 是否是连击状态
    public bool continueAttackCombo;

    void Awake()
    {
        playerController = GetComponent<PlayerController>();
        charactorState = GetComponent<CharactorState>();
    }

    public void combatEvent()
    {
        Debug.LogWarning("state is " + charactorState.curState);
        if (charactorState.curState != UnitState.ATTACK)
        {
            // 是否在攻击窗口内
            bool insideComboWindow = (lastAttack != null && (Time.time < (lastAttackTime + lastAttack.duration + lastAttack.comboResetTime)));

            if (insideComboWindow && !continueAttackCombo && attackIndex < attackCombo.Length - 1)
            {
                // 继续攻击
                attackIndex++;
            }
            else
            {
                // 重置攻击
                attackIndex = 0;
            }

            doAttack(attackCombo[attackIndex], UnitState.ATTACK);

        }
        if (charactorState.curState == UnitState.ATTACK && !continueAttackCombo && playerController.pc.isGround)
        {
            if (attackIndex < attackCombo.Length - 1)
            {
                // 已经处于攻击状态,且不是连续攻击 将连续攻击状态打开
                continueAttackCombo = true;
                return;
            }
        }
    }

    public void doAttack(Damage damage, UnitState state)
    {
        Debug.Log("animationTrigger is " + damage.animationTrigger);
        if (damage.animationTrigger == "attack3")
        {
            Debug.Log("attack3");
        }
        lastAttackTime = Time.time;
        lastAttack = damage;
        lastAttack.inflictor = this.gameObject;
        charactorState.SetState(state);
        playerController.playerAnimation.setTrigger(damage.animationTrigger);
        Invoke("Ready", damage.duration);
    }

    public void Ready()
    {

        Debug.LogWarning("Ready");
        if (continueAttackCombo)
        {
            // 重置是否继续连招动作 因为这个时候玩家没有触发攻击动作
            continueAttackCombo = false;
            if (attackIndex < attackCombo.Length - 1)
            {
                attackIndex++;
            }
            else
            {
                attackIndex = 0;
            }

            Debug.LogWarning("连招" + attackCombo[attackIndex].animationTrigger);

            if (attackCombo[attackIndex] != null && attackCombo[attackIndex].animationTrigger.Length > 0)
            {
                doAttack(attackCombo[attackIndex], UnitState.ATTACK);
            }
        }

        // 重置玩家状态
        charactorState.SetState(UnitState.IDLE);
    }

    // Update is called once per frame
    void Update()
    {

    }
}

三:攻击窗口

如果当前主角的状态不是攻击状态,检查是否在攻击时间窗口内,如果在攻击时间窗口内就进行攻击索引的累加,否则攻击索引从0开始

if (charactorState.curState != UnitState.ATTACK)
        {
            // 是否在攻击窗口内
            bool insideComboWindow = (lastAttack != null && (Time.time < (lastAttackTime + lastAttack.duration + lastAttack.comboResetTime)));

            if (insideComboWindow && !continueAttackCombo && attackIndex < attackCombo.Length - 1)
            {
                // 继续攻击
                attackIndex++;
            }
            else
            {
                // 重置攻击
                attackIndex = 0;
            }

            doAttack(attackCombo[attackIndex], UnitState.ATTACK);
return;

        }
        if (charactorState.curState == UnitState.ATTACK && !continueAttackCombo && playerController.pc.isGround)
        {
            if (attackIndex < attackCombo.Length - 1)
            {
                // 已经处于攻击状态,且不是连续攻击 将连续攻击状态打开
                continueAttackCombo = true;
                return;
            }
        }

猜你喜欢

转载自blog.csdn.net/lck8989/article/details/132272975
今日推荐