Unityでの剣を振る方法(3D)
前回までの記事で以下のように自作キャラを動き回らせることが可能となった。前回までの記事↓
TPSのキャラ移動
ジャンプ
ダッシュ実装
自作キャラを動き回らせる
今回はUnityの3Dゲームで左クリックした時にキャラが剣を振ることができるようにしていこうと思う。
自作キャラの作り方と動かし方目次
素材を入手する剣を持たせる
剣を振る
目次にもどる
素材を入手する
まずはアセットストアから素材を入手しよう。剣自体と剣を振るアニメーションが必要となる。今回は以下のフリー素材を使用することにした(2023年3月現在はフリー)。
・剣素材
・剣を振るアニメーション
以上の素材をダウンロードしてインポートしてUnityに取り込もう。
目次にもどる
剣を持たせる
まず使う剣の素材を決める。プロジェクトビューのMedieval Melee Weapon Packのprefabsに素材が入っている。今回はSword(1)_DHを使っていくことにする。Sword(1)_DHをヒエラルキー欄にドラッグ&ドロップする。その後、Player(動かすキャラ)の手の子要素にすればOK。
ただし子要素にする際にドラッグ&ドロップする位置を間違うと以下のようにエラーが出る。
このエラーはプレハブ化し子要素があるゲームオブジェクトに新たにゲームオブジェクトを追加しようとすると起こる。元々あった子のゲームオブジェクトの位置がずれるので警告される。
よって子要素の一番下の位置(他の子要素に割り込まない位置)にSword(1)_DHをドラッグ&ドロップすればエラーは起きない。例えば以下の位置なら大丈夫だ。
これで剣がPlayerに追従して動くようになる。後は手辺りに剣の取っ手が来るように位置を調整しよう(好みがある場合は剣の大きさなども調整しよう)。
目次にもどる
剣を振る
剣を持たせることができたら、次はアニメーションを設定していく。アニメーションの基本操作がわからない場合は以下の記事へ。アニメーションの基本
今回はプロジェクトビューのExplosiveLLC/RPG Character Mecanim Animation Pack FREE/Animations/2-Hand-Swordフォルダの中にある以下のアニメーションを使っていく。
剣を持ち停止…2 Hand-Sword-Idle-Static
剣を持ち移動…2 Hand-Sword-Run-Forward
剣を振る…2 Hand-Sword-Attack 1
PlayerController(前記事で作ったAnimatorcontroller)に以下のようにIdleとRunに加えてAttackのステートを配置する。
各ステートで以下のAnimationClipを呼び出すようにする。
Idleステート…2 Hand-Sword-Idle-Static
Runステート…2 Hand-Sword-Run-Forward
Attackステート…2 Hand-Sword-Attack 1
好みの問題かもしれないが2 Hand-Sword-Attack 1のアニメーションが遅く感じたので、AttackステートのSpeedを1(初期値)→1,5とすることでアニメーションが再生される速度を上げた。
遷移(矢印)は以下のように配置する。
Attackに向かう遷移は以下のように設定する(Attackのパラメータが0.9より大きい時、遷移する)。
AttackからIdle・Runに向かう遷移は以下のように設定する(Attackのパラメータが0.9より小さい時、遷移する)。
全ての遷移について、「Has Exit Time」のチェックを外すこと(これでアニメーション再生を待たずに次のアニメーションに進めるようになる)。
Float型のパラメータ「Attack」を作成する。
このパラメータ「Attack」の値を操作することで、Idle・RunのステートとAttackのステートを行き来できるように設定していく。
ここで注意点がある。アセットストアから手に入れたアニメーションにはイベントが設定されている可能性があるということだ。
例えば、ExplosiveLLCのRPG Character Mecanim Animation Pack FREEのAnimationsの2-Hand-Swordフォルダにある2 Hand-Sword-Attack 1のFBXファイル(AnimationClipの制御が可能)を見てみよう。選択すると以下のように複数のファイルが連なった形式となっているのがわかる。
FBXファイルを選択してインスペクター欄を見よう。Animationタブを選択し2Hand-Sword-Attack1(ここでAnimationClipと紐づいている)が設定されているコンポーネントのEventsの矢印を選択して開いて欲しい。
少しわかりづらいが白線がある。そこを選択するとHitという名前のメソッドを呼び出すようにイベントが設定されていることがわかる。
スクリプト側でHitのメソッドを作っていなければ、アニメーションが再生された際にエラーとなってしまいゲームが停止してしまう。
同様にHand-Sword-Run-ForwardについてもイベントでFootLとFootRと呼ばれるメソッドが呼び出されるようになっている。
これらについては使わないなら削除するのもアリ。
ただ、Hitの場合はアニメーションの剣の振り終わり(アニメーションの終わりではない)のタイミングで呼び出されるようになっている。攻撃が終了した時間に何か処理を入れるだろうと想定してメソッドを呼び出すようになっている(例えばコンボを作る時などに役立つ)。
同様にFootLとFootRについても足が地面につくタイミングでメソッドを呼び出している。例えば足音などの効果音を入れることを想定されているわけだ。
後々役立つかもしれないので、ひとまずスクリプトに以下のように中身が空の記述を追加してエラーが出ないようにする。
そして2Hand-Sword-Attack1のEventsをもう一度開こう。以下のようにアニメーション終わりを選択し、右クリックしてAdd Animation Eventを選択してイベントを追加する。
呼び出すメソッド名はAttackEndとする。
そしてスクリプトの記述は以下のようにする。
まず追加したのは以下の部分。
if (Input.GetMouseButtonDown(0))と記述することで、左クリックが押された時に中身の処理が行われる。
中身はanim.SetFloat("Attack", 1f);となっている。animにはあらかじめanimatorのコンポーネント(PlayerController指定ずみ)を取得してある。先ほどPlayerControllerで指定したfloat型パラメータAttackに1fを代入する。
これで走っている状態でも停止している状態でもPlayerControllerのAttackのステートへ遷移し、剣を振って攻撃するアニメーションが再生される(Attackのパラメータが0.9より大きくなったため)。
そして剣を振る「2Hand-Sword-Attack1」のアニメーションが終わったタイミングでイベントが発生しAttackEndのメソッドが呼び出されることになる。
AttackEndのメソッドは以下のように記述してある。
anim.SetFloat("Attack", 0f);と記述することでAttackパラメータに0が代入される。AttackのステートからIdleまたはRunのステートに遷移が行われる(Attackのパラメータが0.9より小さくなったため)。
以上の作業を行った後に再生を行えば、以下のように剣を持った状態で停止・移動を行え、左クリックすることで剣を振って攻撃できる。
続きの記事は以下。
コンボ攻撃