一: 連招思路
首先人物角色上有三個攻擊實例對象 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 framevoid 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);}if (charactorState.curState == UnitState.ATTACK && !continueAttackCombo && playerController.pc.isGround){if (attackIndex < attackCombo.Length - 1){// 已經處于攻擊狀態,且不是連續攻擊 將連續攻擊狀態打開continueAttackCombo = true;return;}}