チワ裏

とあるゲーム作りたい人のチラシの裏

Unityで3Dモデルを動かして剣で敵をぶっ飛ばす実装メモ

3Dモデルをちゃんと動かすゲームを作ってみたくなったので試しに作ってみました。

実装手順

まずは使用したアセット(無料のやつです)

キャラクター Strong Knight (つよそう)
いい感じの騎士?のアセット
https://assetstore.unity.com/packages/3d/characters/humanoids/strong-knight-83586

スクリプト Free Footsteps System
モデルの動きやアニメーションを思い通りに実装できるアセット
https://assetstore.unity.com/packages/tools/audio/free-footsteps-system-47967

アニメーションやエフェクトは適当にどうぞ

ヒエラルキーの構成

f:id:tiwaluna:20170919220127p:plain

・top_down_camera_pivot
Standert AssetのMultipurposeCameraRigみたいなやつっぽい。
Targetにtop_down_controllerを設定する。
f:id:tiwaluna:20170919220548p:plain

・top_down_controller
このオブジェクトの子にキャラクターの3Dモデル(kinghtprefab)を配置する。
f:id:tiwaluna:20170919220553p:plain

上記はFree Footsteps Systemのデモシーンのオブジェクトに既に設定されているので流用して改造できます。

アニメーションの実装

最終的なアニメーション図 f:id:tiwaluna:20170919221336p:plain

Free Footsteps Systemのスクリプトを改造していきます。
アセットに付いている、TopDownController.csでモデルの制御ができます。
これをアタッチすると、移動キーに合わせたオブジェクトの移動と回転が実装されます。すげぇ

次に任意のアニメーションを再生できるようにします。
TopDownController.csのコードでは歩行時にAnimatorのパラメーターのmoveをtrueにすることでアニメーションを遷移させています。
このスクリプトを以下のように改造して対応するアニメーションを増やします。


void UpdateAnimator() {
  …
  <既存のコード>
  …
  //移動キーのいずれかが押されていればtrue、押されてないならfalse
  isMoving = Input.GetButton(“Horizontal”) || Input.GetButton(“Vertical”);  

   //tureかfalseが設定される
  thisAnimator.SetBool(“move”, isMoving); //tureかfalseが設定される
}

これを応用すれば、
isRunning = isMoving && Input.GetKey(KeyCode.LeftShift);
isAttack = Input.GetKey(KeyCode.Z);

thisAnimator.SetBool(“run”, isMoving);
thisAnimator.SetBool(“attack”, isRunning);

みたいな感じでダッシュ、攻撃のアニメーションフラグを設定できます。 AnimationControllerにちゃんとパラメーターを用意するのも忘れないようにしましょう。


剣で敵を吹き飛ばせるようにする

キャラクターのモデルをこんな感じで改造してみました。

f:id:tiwaluna:20170919222829p:plain

変更した点は元モデルでは剣のモデル(dagger)を腰につけているんですが、daggerをR_elbowの子の位置に設定します。
僕の使ったアニメーションではこれで剣を振るう動きが作れました。
また、不要なパーツは非表示か削除しておきます。

daggerのメッシュに敵が当たったときに攻撃判定としたいので、daggerにMesh Colliderをアタッチします。
また、Mesh ColliderはOnTriggerEnterを使って接触の判定をしたいので、isTriggerを設定します。
そして敵を吹き飛ばすスクリプトを作ってアタッチします。

ブログ用 当たったオブジェクトを吹き飛ばすUnityスクリプト

解説

OnTriggerEnterで大体の処理を行ってます。

  • 敵の判定
    今回は敵にenemyタグをつけて判定するので、 if (other.gameObject.tag == “enemy”)で判定。

  • 攻撃アニメーションの判定
    if( (animatorStateInfo.IsName(“attack”) || animatorStateInfo.IsName(“jump attack”) )
    で攻撃アニメーションが再生されているかどうかを攻撃アニメーションの名前で判定します。

    • また、AnimatorStateInfoの情報は取得する前に
      rootAnimator.Update(0);
      で更新しないと最新のAnimatorの情報を取得できないので注意。
  • 攻撃判定
    0.2f < animatorStateInfo.normalizedTime && animatorStateInfo.normalizedTime < 0.8f
    animatorStateInfo.normalizedTimeで再生中のアニメーションの進捗を取得できます。
    0%(再生開始) ~ 100%(再生終了)
    今回は20%~80%の間で、剣を振っている最中のみ攻撃判定を出すようにします。

  • 吹っ飛ばす!
    rigit.AddForce(transform.root.forward * 25, ForceMode.Impulse);
    敵にRigitBodyがある前提ですが、こいつで吹き飛ばします。ForceMode.Impulseでは相手の質量(Mass)の影響を受けて、瞬間的に力を加えます。適切な値を設定します。

  • その他
    effectの部分は適当にすきなものをどうぞ。
    effectはプレハブを剣と敵の中間の位置に生成されます。


以上で実装は終わりです。正直ただのアセット紹介なんだよなぁ・・・。
説明が抜けていたらすみません。

完全にブログ放置してたからこれからは徐々に記事を書いていきたいなぁ…