mieki256's diary



2024/12/13(金) [n年前の日記]

#1 [godot] Godot Engineにblenderで作成したモデルデータをインポートする

_昨日 に続き、Windows10 x64 22H2 + Godot Engine 4.3 64bit で、ゴルフゲームっぽいものを作成できそうか実験中。

コースのモデルデータを作らないと実験できないよなと…。そのあたりを試していた。

blenderで地形モデルデータを作成 :

ゴルフコースに相当するモデルデータは、blender で作成したい。blender 3.6.18 LTS を利用して作業した。

まずは blender上の単位を合わせないといけない。シーンタブを選んで、単位を設定。単位系はメートル法、長さはメートルになっていることを確認。

godot3d02_ss01.png

まあ、ゴルフ関係って、メートルじゃなくてヤードが多いけど…。Googleで「360ヤード メートル」と打って検索すれば変換値を出してくれるので、それでどうにか…。


ゴルフコースの大体の長さを測りつつ作業していきたい。メジャーツールがあるので、それを使って距離を測る。

godot3d02_ss02.png

  • メジャーツールは、マウスの左ボタンを押したままドラッグすれば線が引かれて、その線の長さを表示してくれる。
  • Ctrl + 左ボタンで頂点に吸着(スナップ)してくれる。Ctrlキーを押すと吸着中を示す丸が表示されるので、その状態で頂点上で左ボタンを押したままドラッグする感じで操作する。
  • メジャーの削除は、消したいメジャーが選ばれている状態でXキー。


ポリゴンの表裏が統一されてないと、Godot Engine に持っていった時にポリゴンが表示されなかったりするので、表裏についても確認しておく。ビューポートオーバーレイ(?)の設定で、面の向き、にチェックを入れると、表が青、裏が赤で表示される状態になるので、視覚的に確認できる。

godot3d02_ss03.png

godot3d02_ss04.png


ポリゴンの表裏を統一させたい時は…。基本的には、ポリゴンを全選択して、メッシュ → ノーマル → 面の向きを外側に揃える、を選べば良さそう。
  • Alt + N でノーマル(法線)に対する処理のメニューが表示される。
  • あるいは Shift + N で面の向きを外側に揃えることができる。


モデルデータができたら、Wavefront(.obj)形式でエクスポートする。ファイル → エクスポート → Wavefront (.obj) を選ぶ。

godot3d02_ss05.png


今回は地形モデル部分を選択した状態で、対象:選択中のみ、メッシュの三角形化、にチェックを入れてエクスポートした。

godot3d02_ss14.png


これで、.obj と .mtl がエクスポートできた。

ちなみに、blender からエクスポートされた .obj, .mtl を使うと、ポリゴンの色が全体的に暗くなる。blender はポリゴンの色をガンマ補正しながら表示しているけれど、.obj でエクスポートするとマテリアルカラーはガンマ補正されない値で出力されるので、他の何かにインポートされると色合いが変わる。できるだけ色を近づけたいなら、.mtl の各値を補正するか、インポート先でマテリアルカラーを設定し直す必要がある。

_mieki256's diary - blenderでobjをエクスポートした際の色を補正

一応、今回作成したモデルデータを置いておきます。実験用の仮モデルデータぐらいにはなるんじゃないかなと…。

_golf_course_take02.zip

Godot Engineでインポートする :

blender 3.6.18 LTS からエクスポートした .obj, .mtl を Godot Engine 4.3 64bit にインポートする。

ちなみに、Godot Engine 4.3 32bit版で処理すると .glb や .fbx をインポートできずに Godot が落ちるので、Godot 64bit版を使ったほうがいいと思う。64bit版なら落ちない。まあ、.obj をインポートする分には32bit版でも落ちないけれど…。

プロジェクトフォルダの中にモデルデータをコピーすれば、Godot でプロジェクトを開いた際にモデルデータが自動でインポートされる。今回は、imports という名前のフォルダを作成して、その中にモデルデータを入れておくことにした。

MeshInstance3Dノードを追加。Mesh のところが「空」になっているので、インポートした .obj をドラッグアンドドロップしてやる。

godot3d02_ss06.png


.obj がメッシュとして選択された。

godot3d02_ss07.png


このメッシュから、コリジョン用のモデルデータを作りたい。MeshInstance3D が選択されてる状態で、メッシュ → コリジョン形状を作成... を選ぶ。

godot3d02_ss08.png


ダイアログが開くので、ノードの配置場所、シェイプの型を選ぶ。

godot3d02_ss09.png


CollisionShape3D が新規作成されてシーンに追加された。

godot3d02_ss10.png


CollisionShape3D を選択すると、プレビューウインドウ内で、コリジョン用モデルデータが作られていることが分かる。

godot3d02_ss11.png

ボールやカメラを動かす :

RigidBody3D をボール相当にしたい。キーボードのキーを押したら、前後左右に動いたり、前方に飛び出したりするようにしたい。

RigidBody3D にスクリプトをアタッチする。内容は以下のようにした。

_rigid_body_3d.gd
extends RigidBody3D

@export var speed: float = 20.0
@export var shot_speed: float = 30.0
var target_velocity = Vector3.ZERO
var init_pos = Vector3.ZERO

func _ready():
    init_pos = global_position


func _process(delta):
    if Input.is_action_just_pressed("ui_home"):
        global_position = init_pos
        
    if Input.is_action_just_pressed("ui_accept"):
        apply_central_impulse(Vector3(0, shot_speed, -shot_speed))
        
    var d = Vector3.ZERO
    if Input.is_action_pressed("ui_left"):
        d.x = -1
    if Input.is_action_pressed("ui_right"):
        d.x = 1
    if Input.is_action_pressed("ui_up"):
        d.z = -1
    if Input.is_action_pressed("ui_down"):
        d.z = 1
    if d != Vector3.ZERO:
        d = d.normalized()
        d.x *= speed
        d.z *= speed
        apply_central_force(d)

  • @export を使うと、Godotの画面上で、GUIで値を変更できるようになる。
  • _ready() は、そのオブジェクトが画面に出現した際に呼ばれる関数。
  • _process(delta) は、毎フレーム呼ばれる関数。delta には前フレームからの経過秒数が入っている。単位は秒。
  • apply_central_impulse() で、瞬間的に速度を追加できる。
  • apply_central_force() で、力を加える。
  • Input.is_action_just_pressed() で、キーが押された瞬間を検知できる。
  • Input.is_action_pressed() で、キーが押されているかどうかを検知できる。

上記のスクリプトでは、以下のキー判定と処理が書いてある。
  • Homeキー ("ui_home") : 初期位置に戻る
  • スペースキー ("ui_accept") : 前方に飛んでいく
  • カーソルキー : 前後左右に転がる


カメラにもスクリプトをアタッチする。ボールを追いかけるような処理を追加したい。

_camera_3d.gd
extends Camera3D

@export var target: Node3D
@export var offset: Vector3 = Vector3(0, 3, 8)
@export var follow_speed: float = 12.0

func _ready():
    var tpos = target.global_position + offset
    global_position = tpos
    look_at(target.global_position, Vector3.UP)
    # rotation.x = 0

func _process(delta):
    if not target:
        return
        
    var tpos = target.global_position + offset
    global_position = global_position.lerp(tpos, follow_speed * delta)

  • target には、追いかけたいオブジェクトを指定しておく。
  • target で指定されたオブジェクトのグローバル座標に、オフセット値を追加した座標を、カメラ位置にしている。
  • lerp() という補間を行う関数を使っているので、ほんのちょっとだけ目標座標に遅れる感じで動いてくれる。

結果 :

以下のような結果になった。




blender で作った地形モデルデータの上に、ボールがぽとりと落ちて止まってくれた。

ただ、できれば、地面に落ちたボールがポーンポーンポーンと跳ね返ってほしい…。

跳ね返りの設定を変更する :

ボール担当の RigidBody3D、もしくは、地面相当の StaticBody3D の、Physics Material Override を設定して、跳ね返りを設定する。

StaticBody3D を選択した状態で、Physics Material Override が「空」になっているので、クリックして「新規 PhysicsMaterial」を選択。

godot3d02_ss12.png


Bounce を、0.0 より大きい値にする。0.5 とか 0.75 とか。

godot3d02_ss13.png


これで試すと…。




多少は跳ね返るようになってくれた。

課題 :

ちょっとはそれっぽい見た目になってきたけど、色々な課題が…。

坂に落ちると、ボールがどこまでも転がって行ってしまう。どうやったら止められるのか…。

落ちた場所によって跳ね返り方を変えたい。でも、落ちた瞬間と、どんな種類のポリゴンに落ちたかを、どうやって調べたらいいのか…。

飛ばしたボールが途中でどんどん失速している気がする。挙動としては正しいのだろうか…?

どんな風に飛んでいるのかボールの軌跡を描画したいけど、どうしたらいいのか…。

以上、1 日分です。

過去ログ表示

Prev - 2024/12 -
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project