U
タブ 02キャラクターと戦闘9 レッスン — タップで開く
03 / 09 · 10 分
キャラクターと戦闘

Animator のステートマシン

ここまでのプロジェクト

Assets/

Scenes/

Arena.unity

Knight

Scripts/

PlayerMovement.csCharacterStats.csPlayerAnimator.cs

Animations/

AC_KnightLocomotion blend tree

すでにあるものこのレッスンで追加

Knight は PlayerMovement で動くようになりましたが、T ポーズのまま凍り付いて滑るように動いています。このレッスンでは足を与えます。

コードがクリップを直接再生することは決してありません。パラメータを設定するだけ——どのクリップを指すのかは Animator が決め、その間でブレンドします。

アニメーション図

左のキャラクターが、右で光っている状態をそのまま演じるのを見てください——そして下にある 3 つのパラメータだけが、コードが触れる唯一のものです。

コントローラーをセットアップする

  1. 1

    Project ビューで Create▸Animation▸Animator Controller を選び、AC_Knight と名付けます。

  2. 2

    Knight を選んで Animator コンポーネントを追加し、AC_Knight を Controller に、モデルの Avatar を Avatar へドラッグします。

  3. 3

    Window▸Animation▸Animator ウィンドウを開き、Idle クリップをドラッグして入れましょう——オレンジ色のデフォルト状態になります。

  4. 4

    Parameters tab で Speed(Float)、IsGrounded(Bool)、Attack(Trigger)を追加します。

歩行と走行を別々の状態にするより Blend Tree の方が得です

  1. 1

    Animator 内で右クリック → Create State → From New Blend Tree。Locomotion と名付けてデフォルトにします。

  2. 2

    それをダブルクリックし、Blend パラメータを Speed に設定してモーションを 3 つ追加します:Idle を 0、Walk を 2、Run を 6。

  3. 3

    これで float ひとつが idle → walk → run を滑らかにクロスフェードします。移動のための遷移矢印は一切不要です。

コードから駆動する

PlayerAnimator.cs — on the Knight, next to PlayerMovement
using UnityEngine;

[RequireComponent(typeof(Animator))]
public class PlayerAnimator : MonoBehaviour
{
    private Animator anim;
    private CharacterController cc;

    // hashes are faster than strings
    private static readonly int SpeedHash    = Animator.StringToHash("Speed");
    private static readonly int GroundedHash = Animator.StringToHash("IsGrounded");
    private static readonly int AttackHash   = Animator.StringToHash("Attack");

    void Awake()
    {
        anim = GetComponent<Animator>();
        cc = GetComponent<CharacterController>();
    }

    void Update()
    {
        // horizontal speed only — vertical fall must not look like running
        Vector3 flat = new Vector3(cc.velocity.x, 0f, cc.velocity.z);

        anim.SetFloat(SpeedHash, flat.magnitude, 0.1f, Time.deltaTime); // 0.1f = damping
        anim.SetBool(GroundedHash, cc.isGrounded);

        if (Input.GetMouseButtonDown(0))
            anim.SetTrigger(AttackHash);
    }
}
  • SetFloat の 3 番目と 4 番目の引数は damp 時間と delta time です:値が緩やかに変化するので、ブレンドがカクつきません。

  • Trigger は消費されると自動でリセットされる bool です。Attack のような一回きりのアクションに最適です。

  • StringToHash は static フィールドで一度だけ呼べば十分です:毎フレーム文字列で検索するのは無駄な作業です。

カクつきの 9 割を直す遷移設定

  • プレイヤー操作に即応すべき遷移(攻撃、ジャンプ)では Has Exit Time のチェックを外します。最後まで再生しきる必要があるアニメーションでは入れたままにしてください。

  • Transition Duration は 0.1〜0.2 秒が反応良く感じます。0.3 秒を超えるとキャラクターが酔っているような動きになります。

  • Interruption Source → Current State にすると、新しい攻撃が前の攻撃に割り込めるようになり、キュー待ちになりません。

Animation Events——剣を振ったその瞬間にヒットさせる

ダメージはボタンを押した瞬間ではなく、剣が本当に振り抜かれた瞬間に通すべきです。Animation Events を使えば、クリップの指定したフレームでメソッドを呼べます。

C# スクリプト
// on the same GameObject as the Animator
public void OnAttackHit()      // pick this name in the clip's Events row
{
    Debug.Log("hit frame");
    // damage the enemies in range
}