2020/11/09
「過去にこんなことができた」ということで、参考程度でご参照ください。
というわけで、今回はタイトル通り「空中攻撃」を作ってみます!
至って普通に空中で攻撃を行うものです。
単純ながら、ジャンプ可能なアクションゲームではほぼ必須アクションです。むしろ「何故今までなかったのか」というレベルの話でもあります。
当初は単発攻撃の予定でしたが、「空中でも連続攻撃したい!」となったため、地上攻撃と同じように連続入力で派生するようにします。
アクション性の高いステージほど空中にいる時間は長くなるので、モーション自体の使いやすさも重要なところです。
スクリプト作成
まずはBlenderでアニメーションを作ります。
気合い入れて作る元気はないので、とりあえずマリンパにそれっぽく剣を振ってもらいます。
Unityへインポート後、AnimatorControllerに登録します。
空中攻撃の条件は「空中にいる時に攻撃ボタン」です。
PlayerクラスでCharacterMotor
のisGrounded()
から判定しても問題なさそうですが、「ダッシュ中は発動しない」等の条件も判定することを考えると、ジャンプ系のステートからスクリプトで遷移させる方がよさそうです。
そんなわけで、ボタン押下時にAnimator.Play()
で空中攻撃に飛ばしてしまいます。
以下はボタン押下時にステート遷移を行う「SwitchTriggerByKey
」クラスです。
using UnityEngine; using System.Collections; namespace StateController.PlayerAnimator { public class SwitchTriggerByKey : StateMachineBehaviour { // 入力するキー(ProjectSettings) [SerializeField] protected string inputKey; [SerializeField] protected string parameterName; // Animator.Playを用いて遷移 [SerializeField] protected bool useAnimatorPlay; public override void OnStateUpdate(Animator animator, AnimatorStateInfo stateInfo, int layerIndex) { if (Input.GetButtonDown(inputKey)) { switchTrigger(animator); } } private void switchTrigger(Animator animator) { if (useAnimatorPlay) { animator.Play(parameterName); } animator.SetTrigger(parameterName); } } }
inputKeyに(InputManagerの)攻撃ボタン名、parameterNameにAerialAttack1~3を設定します。
攻撃モーションが終わるまで遷移しないので、useAnimatorPlayにはチェックを入れないようにします。
この記事的には空中攻撃実装のためですが、実際は他のステートでも使えます。
自分は「待機中に攻撃ボタンで~」「移動中にダッシュボタンで~」など、いろいろなステートに付けていたりします。
条件として「ボタンが離された時」を入れておくと、チャージ攻撃などの溜めが必要な入力の場合でも対応できます。
その場合は、Triggerではなくfloat等で判断した方が良いかもしれないです。
空中攻撃2~3にも同様にスクリプトを追加し、遷移条件を設定します。
基本的にはExitTimeにチェックを入れ、インスペクターで遷移タイミングを設定していい感じに繋ぎます。
攻撃判定の生成に関しては過去記事で話題にしているので割愛します。
攻撃ヒット時の浮遊状態の実装
連続入力で(マリンパの場合は)3段目まで出せるわけですが、地上と違ってジャンプ中だったり落下中だったりするため、そのままではフルヒットさせるのは困難です。
かと言って攻撃する度に浮くようにした場合、空中で素振りしまくって延々と飛べるのも問題です。
なので、「攻撃がヒットした時」に少しだけ浮くようにします。
敵に当たればそのまま連続入力でフルヒット…というのが理想ですね。
ステート側のスクリプトでやるのは効率が悪いので、攻撃判定のOnTriggerEnter()
で判定後、Playerクラスの関数を呼ぶようにします。
public void callAttackHit(PlayerHit playerHit) { if (stateInfo.IsTag("Attack")) { charMotor.movement.velocity.y = 20; } }
CharacterMotor.movement.velocity
はキャラクターの速度です。
Y軸を一時的に20に設定することで、キャラクターが少しだけ浮きます。
やや強引な方法ですが一番簡単だったのでこれでいきます!
まとめ
ということで、空中攻撃を実装してみました!
最終的にはこんな感じに。
使う機会が多いアクションなので、余裕があればもっと改良していきたいところです。