一: 连招思路
首先人物角色上有三个攻击实例对象 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;
}
}