ゲームエンジンgodot4.0で3Dスマホゲームを作りたいと思いますが、その前にお勉強しています。
Godot_v4.0-rc1_win64.exe.zipを使用しています。
目的
Node3Dを理解する
Godot3.5の時はSpatialという名前でしたが、4.0で名称がNode3Dに変更しました。
Node3Dとは
Godot 3DエンジンはNode3Dを継承(inheritance)するノードを3D空間に表示します。
Node3Dを継承しているノードとは、子ノードを追加するウィンドウでNode3Dにぶら下がっているすべてのノードです。今まで登場したMeshInstance3Dや、DirectionalLight3D、Camera3DもNode3Dを継承しているため3D空間に配置することができます。
MeshInstance3Dを選択して、右側のインスペクタを表示すると上の方には自身のMeshInstance3Dの設定・属性値が表示されています。継承元の情報・属性は下の方に表示されていて、Node3Dの情報・属性などがあります。他のNode3Dを継承したノードもインスペクタの下の方にNode3Dがあります。
global座標とlocal座標
シーンのルートノードを配置する座標系をglobal座標系といいます。
ノードを親子関係にした場合、子は親のlocal(ローカル)座標系に存在します。
ここでは雪だるまをつくって、ローカル座標の便利さを確認しようと思います。
新規プロジェクトを作成して、3Dシーンを押下してNode3Dを追加します。
Node3Dを右クリックしてMeshInstance3Dを追加してください。名称をMeshInstance3D_bodyに変更してください。
インスペクタのMeshInstance3DのMeshのをクリックして、新規SphereMeshを選択します。
Node3Dを右クリックしてMeshInstance3Dを追加してください。名称をMeshInstance3D_headに変更してください。
インスペクタのMeshInstance3DのMeshのをクリックして、新規SphereMeshを選択します。
MeshInstance3D_headを選択して、Node3DのTransformのpositonのyを0.7mに設定してください。
次にMeshInstance3Dの球をクリックしてください。Meshの詳細パラメータが表示されます。
radius(半径)を0.5から0.3mにして、Heightを0.6mにすると少し小さいに球になります。
雪だるまが完成しました。
では体を移動しましょう。
MeshInstance3D_bodyを選択して、ギズモの赤い矢印をドラッグして左にうごかしましょう。
頭(MeshInstance3D_head)はついてきませんね。
このときのインスペクタ内のNode3D-Transform-positionのXの値を覚えておきましょう。
では次にMeshInstance3D_headを選択して、ギズモの赤い矢印をドラッグして左に動かして、体の上に頭が乗るようにしましょう。
このときのインスペクタ内のNode3D-Transform-positionのXの値を確認すると、MeshInstance3D_bodyと同じような値になっていると思います。
でも本当は体を動かしたときは、頭も一緒についてきてほしいですよね。
その場合は、ベースとするノードを決めて、ほかの一緒に動いてほしいノードはその子供にします。
(下記操作をする前に、MeshInstance3D_headとMeshInstance3D_bodyのXの値は同じにしてください。)
シーンの中でMeshInstance3D_headをドラッグアンドドロップしてMeshInstance3D_bodyに重ねると、MeshInstance3D_bodyが親でMeshInstance3D_headが子供になってぶら下がるようになります。
あたらめてMeshInstance3D_bodyを選択してギズモを表示して、赤い矢印をドラッグすると頭がついてきます。
この時にMeshInstance3D_headを選択してインスペクタ内のNode3D-Transform-positionのXを確認すると、0mになっていると思います。
はじめの例ではglobal座標系にbody(MeshInstance3D_body)とhead(MeshInstance3D_head)の位置を定義していました。そのためbodyを動かしてもheadはそのままの位置でした。
後の例ではノードを親子にしました。
Node3Dは親子にすると、子のNode3D(head)は親(body)の位置からの差分(位置、回転)を表すようになります(local transform)。今回の例では、頭の位置は体の中心からY軸方向に0.7mにあるという相対的な位置関係を表しています。
そのため、bodyを移動しても、head(子)はbody(親)との位置関係を保持するため、headがbodyについてきます。headのx座標はbodyとの関係を保持しているので、0mのままです。
Godotの3D表示内の赤、青、緑の軸の座標系、3次元空間全体をglobal座標系といいます。
それに対して、個々のノードが持つ座標系をローカル座標系といいます。
これはとても便利な仕組みで、複数のノードで構成されているキャラクターを動かすときに、ひとつの親ノードを動かすだけで全部ついてくるし、多関節なものもうまく管理することができます。
global座標とlocal座標の注意点
ノードを追加するときの階層を意識する必要があります。
BodyとGunをもつ砲台から弾丸を発射する場合に、その弾丸を追加する例で考えます。
砲台Node3D_Palayer_01 親ノードにBody01とGun01とGun01から発射されたBullet01をぶら下げています。
砲台Node3D_Palayer_02 親ノードはBody02とGun02のみが子ノードとして、Bullet02はルートノードにぶら下げています。
砲台Node3D_Palayer_01 を選択して移動すると、砲台Node3D_Palayer_01の子のBullet01も一緒についてきてしまいます。多くの場合意図しない動作になります。
砲台Node3D_Palayer_02選択してを移動すると、Bullet02はついてきません。
こうしてエディターで見ると当たり前でわかりやすいのですが、プログラムからBulletを追加するときには、背景=global座標系を持つノードにBulletを追加する必要があります。
以上