3Dプロジェクトの作成 ①3Dモデルインポート&アニメーション&シェイプキー

概要

Godot Engineでの3Dプロジェクトの作成と、3Dモデルのインポート方法について解説します。
他記事と内容がかぶってしまうので、シンプルな2Dプロジェクトは作成できる程度の基本操作は出来る前提で記載します。

<使用ソフト>
Godot Engine:4.0beta1(理由は後述)
Blender:3.3 ※3Dデータはダウンロードできるようにしていますので、そのまま使えばBlenderは不要です。

はじめに

久々の投稿となってしまいました。
私事ではあるのですが、在籍していた企業を9月で退職し個人事業主で活動することとなりました。
フリーの3Dクリエイター(主にモデリング)として活動しつつ、3DゲームやVR/XR関係のことも出来ればと言ったところです。
上記事情もあり、Godot Engineに触れる時間も増えたので、これからは更新を増やしていこうと思います。(決意)

Godot Engine 4.0beta1について

3Dプロジェクトの作成の記事では基本的にGodot Engine 4.0の最新版を使用していきます。
本来はこういうTip集で正式リリース版ではないものを使用するべきではないかと思います。
ただしあえてbeta版を使用する理由として、

・beta版なので正式リリース版と大きく操作が変わるとは考えにくい(逆に今3.xで書いてしまうと年内には古い情報になってしまう)
・beta版の操作方法など最新の情報が提供できる
・上記2つを建前にして4.0版を色々試したい

個人的には3.xよりも4.0の方がVisualScriptを廃止したことを除き、おおむね良い変化点が多いかなと思います。

3Dプロジェクトの作成

新規プロジェクトを作成します。
この際、使用するレンダラーはどちらでも良いのですが後からでも変更できるので、ひとまず軽いVulkan Mobileで良いでしょう。

今回は3Dプロジェクトの作成なので、ルートノードはNode3dにします。

3Dモデルの形式について

Godot Engineに使用する3Dモデルのファイルですが、今のところ私の環境ではglTF2.0が一番安定しています。
※他の形式はマテリアルが壊れたり、微妙にメッシュがずれていたりすることがある。
glTF2.0にも3つほどファイル形式がありますが、基本的にはglTF Separateというフォーマットを使用してください。
(拡張子は.gltf/.bin/テクスチャーファイルがそれぞれ分離しています)
詳細な理由の説明はしませんが、ざっくり言うと色々と要素が分離していたほうが処理がシンプルだからと思ってもらえればOKです。

事前準備

Godot Engineにインポートする3Dモデルを準備します。
Blenderを使える人は自分で作ってもらっても良いです。その際、ファイルをglTF Separateにすることだけ注意してください。
作れないor作る時間がない人はこちらからZIPファイルをダウンロードしてください。下記のモデルが入っています。

Godot Engineへの3Dモデルのインポート

予めBlender等で出力された.gltf/.bin/テクスチャーをまとめてファイルシステムエリアにドラッグアンドドロップします。

gltfファイルを右クリックし、新しい継承シーンを選択。

すると、読み込んだ3Dモデルの各メッシュやアニメーション等がまとまっているシーンが作成されます。

いったんシーンを保存しておきましょう。

シーンが保存できたら、メインのシーン編集タブに戻って3Dモデルのシーンを配置します。
適当に配置すると、とんでもない位置に配置されるためTransformのポジションの設定をリセットして原点に戻しておきましょう。

各ノードの配置

このままシーンを再生しても灰色の画面が映るだけです。
3Dシーンにはどの領域を映すかの情報(カメラ)と、どういう照明をあてるか(ライト)のノード配置が必要になります。
一旦メインノードの子ノードとして空の3Dノードを配置し、その下に「Camera3d」と「DirectionalLight3d」というノードを配置しましょう。(直接メインノードにカメラやライトを配置しても良いですが、カテゴリごとに空の3Dノードでまとめておくと何かと後で楽です)

カメラの位置を座標軸の矢印を引っ張ったりして位置調整しましょう。回転方向は座標軸と同じ色の球体の曲線をぐりぐり動かすことで調整できます。(変な位置になってもTransformのパラメータをリセットすれば元に戻るので適当に動かしてみてください)
大体こんな位置/回転にすると良い感じになります。

ライトはそのままの位置でも良いですが、せっかくなので影が出る感じも出してみましょうか。
同様に位置や回転を調整して斜めから光が当たるように調整してみてください。

ちょっとわかりにくいですがこんな感じです。

さて、これで再生してみましょう。なんとも言えない雰囲気が漂っていますね。

アニメーションの再生

次はアニメーションを再生しましょう。アニメーションの再生はGDScriptで実行します。
まずは3Dモデルに対してGDScriptを作成しましょう。
この際、メインシーンのModelノードに対してスクリプトを作成するのではなく、Model自体のシーンの編集タブに移動し、Modelノードにスクリプトを適用するようにすると、下記のようにノード名をドラッグ&ドロップで入力出来たりするので、コード入力が楽になります。

この3DモデルにはWaitAnimationという名前でアニメーションがあらかじめ設定されています。
Blenderでのアニメーションの設定方法はRendorPoolさんの記事(https://jp.renderpool.net/blog/blender%E3%81%AE%E3%82%A2%E3%83%8B%E3%83%A1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3/#Blender3D)が参考になります。

このAnimationPlayerノードにあるWaitAnimationを再生するGDScriptは以下です。

extends Node3D

func _ready():
	$AnimationPlayer.play("WaitAnimation")
	pass

さて、extends Node3Dはお決まりの初期から入っている記述ですので気にしなくて良いです。
次に$AnimationPlayerですが、これはModelノードの子ノードであるAnimationPlayerノードの場所を取得しています。
$はget_node()を短縮して書けるようにしたものです。つまり、$AnimationPlayer = get_node("AnimaitonPlayer")です。
アニメーションノードに対し、.play("xxx")でxxxのアニメーションを再生する処理になります。

これを実行すると、モデルが最初に首を振るようになりますね。


(以下余談。コードの書き方が気になる人以外は次のセクションに進んでください。)
ちなみに私は出来るだけ関数内の処理の記載は使い回したいので、以下のように処理を組むことが多いです。

extends Node3D

@onready var _modelanimation := $AnimationPlayer
var _readyanimation = "WaitAnimation"

func _ready():
	_modelanimation.play(_readyanimation)
	pass

ノードの場所やアニメーションの名前を最初に全て定義していまい、実際の処理ではその関数を代入するだけといった形ですね。
こうすることで同じような処理を他でも実装したいときにそのまま使い回し、最初の変数定義だけ修正すれば良いという流れです。
元からIT系の人はどうなのか分かりませんが、組込システム系の出身の人はこのように書く人が多いですね。(おそらくC言語でヘッダーファイルでパラメータを設定することに慣れているからかと)
※IT関係の人、ITやゲーム業界ではこういうコードの組み方だよというのがあれば教えてください。

余談はおいておいて、まず@onreadyですが、これは変数の定義の実行をあえて少しだけ遅らせるキーワードです。
これによりしっかりとシーンが確実に実体化されてから変数が定義されます。
まぁ、今回の例ではonreadyが無くても動くんですが、実体を伴うものに対する変数アクセスを定義する際には癖としてつけておくようにした方が良いです。
以下、GDScriptリファレンスより抜粋。

onreadyスクリプトがアタッチされているノードとその子がシーンツリーの一部になると、変数を初期化します。

あと、Godot3.x以前の人はonreadyの最初のアットマークを外して入力してください。
Godot4.0から一部キーワードの置換や修正が入りました。Godot4.0ではonreadyやtool、exportなどは最初にアットマークをつける必要があります。
また代入が=ではなく、:=となっているのは話始めると本題の趣旨からそれてしまうので解説はしません。(実は=でも動くんですけどね)
特に理由は気にせず、$(=get_node)の代入は:=と覚えてもらってよいかと思います。(雑)

シェイプキーのコントロール

知っている方もいるかもしれませんが、3Dモデルにはシェイプキーという概念があります。
シェイプキーとは3Dモデルの段階でモデルの形状にたいしてパラメータを設定しておき、後からパラメータをいじるだけで形状が変更できるようになる機能です。
例えば目のまぶたの開き具合をシェイプキーにして、パラメータとしてコントロールすることでまばたきやウインク、目を閉じるなどの動作をすることがわざわざアニメーションを設定しなくても出来るようになります。(まばたきはアニメーションで設定してしまった方が楽かもしれませんが)
本記事の学習用モデルにはUdeのモデル内にLongleftArmとパラメータで左腕の長さが調整できるようになっています。(ゴム〇ムのピストル用に。嘘です。)
Blenderでのシェイプキーの作成方法は「Blender シェイプキー」で調べればたくさん出てくるのでそちらを参照ください。

エディタからパラメータを調整するだけだとつまらないので、GDScriptで動かしてみましょうか。

extends Node3D

func _ready():
	$AnimationPlayer.play("WaitAnimation")
	pass

func _process(delta):
	if($"アーマチュア/Skeleton3D/Ude".get("blend_shapes/LongleftArm") <= 0.99):
		$"アーマチュア/Skeleton3D/Ude".set("blend_shapes/LongleftArm" ,$"アーマチュア/Skeleton3D/Ude".get("blend_shapes/LongleftArm")+0.1*delta)
	pass

ちょっと記述が長すぎますね。さすがに変数にパスやパラメータ名は代入しましょうか。

extends Node3D

@onready var _ude := $"アーマチュア/Skeleton3D/Ude"
var _udelong = "blend_shapes/LongleftArm"

func _ready():
	$AnimationPlayer.play("WaitAnimation")
	pass

func _process(delta):
	if(_ude.get(_udelong) <= 0.99):
		_ude.set(_udelong ,_ude.get(_udelong)+0.1*delta)
	pass

ノード名.get("パラメータ名")で現在のパラメータの値を取得します。
ノード名.set("パラメータ名",値)で現在のパラメータに指定の値をセットします。

このプログラムでやっているのは、腕の長さLongleftArmの値が0.99以下の時に秒速0.1のペースでLongleftArmの値を増やしていくという処理です。
※X*deltaで近似的に秒速Xにすることが出来ます。

これで実行すると徐々に腕が延びてきます。
首を動かしながら腕が延びるとか、ゴムゴ〇というより、どちらかと言うとホラーに近いですね。

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です