今回はアニメーションはいったん無視してT-Pose で動けるようにキャラコン(Third Person Character Controller)をGDScript で作ります。移動方向にスムーズ回転させます。CharacterBody3D ノードは、スクリプトを付けようとすると、デフォルトで簡易コントローラが書いてあるものがくっ付きます。なんと、これをチョイ修正するだけでイイ感じになります。俺にもできたので誰にでもできると思います。今回はこの追加変更箇所のメモです。
1. スクリプトを付ける
❶ 当然CharacterBody3D ノードに付けますので、これを選択して[スクリプト付けるボタン] を押す
❷ テンプレがCharacterBody3D 専用のになってるから、このまま利用させてもらう
これだけでもう動くのですが、「カメラ操作」と「移動方向にスムーズ回転」が出来るようにチョイ修正していきます。面倒なので、画像で貼っておきます。
ハイ完成です。・・・というわけにはいかないと思いますので、以下簡単に解説っておきます。
2. カメラ操作の前に
main scene の再生時、マウスカーソルが煩わしいのでmouse_mode
を変えます。またゲームを抜ける時にウインドウの右上バツボタン[X] が押せるようカーソルが見えるように変えます。mouse_mode
が詳しく知りたい方はマニュアルのInput
クラスを参照してください。
❶ _ready()
関数内でマウスカーソルを画面中央に固定し、見えないようにします。
❷ _unhandled_input()
関数内で、ESC キーを押した時マウスカーソルが見えるカツ動くように戻します。
3. カメラ操作
忘れないうちに先に書いておきます。カメラ操作(又はキャラ操作)でマウスの動きを利用する場合は_unhandled_input()
関数を使います。単なる_input()
関数ではありません。_input()
でやってしまうとUI 関係の処理へ渡す情報と被る事になるので注意です。オプション画面とかを操作してるその裏でカメラとかキャラが動いてるなんて事がキモチワルイと思ったら素直に_unhandled_input()
。
3-1. ノード
シーン内のカメラ操作に関係するノードを見ます。前にも書きましたが、私はダブル・カメラピボット・システムを採用しています。
❶ マウスの横の動きをこれに担当させます。カメラを左右に振るダケの仕事をさせます。(キャラの目の高さにずらしておきます)
❷ マウスの縦の動きをこれに担当させます。カメラを上下に振るダケの仕事をさせます。(右肩ショルダーカメラにするので40cm ほど右にずらしておきます)
SpringArm3D とCamera3D は前回の記事を参照の事。
3-2. スクリプト
❶ @onready var
でノードを変数に登録します。ちなみに[Scene] のノードを「Ctrl + ドラッグ」でスクリプト書き書き画面に持って来ると、@onready var
の変数に出来ます。
❷ 同様@onready var
で登録。
if event is InputEventMouseMotion:
というのはマウスに動きがあったらtrue
になります。まー、「もしイベントがマウスモーションだったら~する」という事だと思っておけばいいでしょう。
❶ ここでマウスの左右の動きの差分を取得してY 軸回転させます。rotate_y()
は中身がラジアンなのでマウスセンシを掛け算して回転スピードを調整します。たぶん、思ったのと反対に回りますので、マウスセンシの方にマイナス付けるか、掛け算の時にマイナスを付ければいいでしょう。
❷ こっちはマウスの前後の動きの差分を取得してX 軸回転させます。rotate_x()
も同様、中身がラジアンです。回転スピードの調整は必要です。これもたぶん、思ったのと反対に回りますので、そこもマイナス付けて調整すればいいでしょう。
❸ カメラがひっくり返ってまで回らないように❷のノードのX 軸の回転角度をクランプ(範囲を限定)させます。clampf()
はfloat 型のクランプです。また、rotation.x
もラジアンです。いちいちdeg_to_rad()
やrad_to_deg()
など使わずに、「180° = 3.14...(PI)」、つまり、「60° = 1.04...」、つまり「1ラジアンはだいたい60°」と思っておけばいいでしょう。
ちなみに、ここでクランプさせるMAX とMIN を指定しています。
カメラ制御はこれだけです。マジで簡単です。カメラピボットを2つのノードで表現する事で、グローバル回転とかローカル回転とかうんたら回転とか、いちいち悩まずrotate_o()
でいいので楽ちんです。
4. キャラ操作
Mixamo 「T-Pose」fbx を使います。本当にfbx のインポートが速くて楽。エクスプローラから[FileSystem] にD&D して、今度は[FileSystem] から[Scene] にD&D すればいいだけ。(ただしアニメもいじるので[Editable Children] はしておく事。)
4-1. ノード
❶ Godot は「-Z が前」。fbx は+Z を向いているので、そのまま使うよりかこのNode3D をひとつかませて、その下にfbx(のインスタンス)を180°回転させて付けるのがイイと思います。
❷ fbx。[FileSystem] からD&D して[Editable Children]。Y 軸は180° 回転させておく。
4-2. スクリプト
❶ [Input Map] を変えたのでそれを反映します。Input.get_ventor()
関数、中身は(左, 右, 前, 後)で書きます。Vector2 型です。
❷ ここがポイントです。CharacterBody3D のbasis
(transform.basis
)を使うのではなく、Y 軸回転用のカメラピボットのbasis
(cam_piv_a.transform.basis
)を使います。これで移動方向がカメラ方向になります。いちいちカメラノードを持って来る必要はありません。
❸❹ これら2行もポイントです。移動方向へキャラをスムーズ回転させるコードです。
いきなりキャラを移動方向へlook_at()
させるのではなく❸で、もし移動方向を向いた時、transform
はどうなるか? というのをlooking_at()
で調べて変数に取っておきます。これが最終的に向く方向と考えていいわけですが、transform
なので、回転だけでなく、位置や拡大縮小情報も含んでいるので注意です。
(もちろん動かすノードはfbx ではなく親ノードです。完成スクリプトを見て、忘れずに@onready var
しておいてください。)
❹でinterpolate_with()
を使って、現在のtransform
を徐々に最終的に持って来たいtransform
(new_transform
)に近づけて行きます。スラープみたいなものですが、このinterpolate_with()
は非常に優秀で、なんでか知りませんが思った通りに動きます。(ひっくり返って遠周りの回転をしないという事。)
(回転スピードにdelta
を掛けてますが、別に掛けないでSMOOTH_R
だけの値で調節してもいいと思います。万一_physics_process()
がぶっ飛んだ場合の対策です・・・要らんかな)
ま~、何という事でしょう、たった2行でスムーズ回転が実現しました。
ラープとかスラープとは何じゃらほい? という人は、下の記事を参考にどうぞ。悩んでますね。
5. これで完成!
です。
今のGodot ならキャラコン、簡単にできますね。デフォルトで付いてくるスクリプトが優秀なので、ちょっと追加・修正するだけでイイ感じに動くようになります。後は、アニメーションを付ければいいだけですね。次回はAnimationTree を使ってアニメするようにします。