2024/12/14(土) [n年前の日記]
#1 [godot] Godot Engine 4.3のRigidBody3Dについて調べてた
_昨日
に続き、Windows10 x64 22H2 + Godot Engine 4.3 64bit でゴルフゲームっぽいものを作れそうかどうか実験中。
RigidBody3D で作ったボールが、StaticBody3Dで作った地面の上をいつまでも転がり続けて悩んでる。どうにかして、どこかのタイミングでピタリと止めたい。RigidBody3D の設定で解決できないものかと調べてた。
とりあえず分かった点をメモしておく。
余談。ボールを球のままにしておくと回転具合がさっぱり分からなかったので、試しに球を箱にしてみたところ、回転具合が分かりやすくなった。コリジョンさえ球になっていれば、見た目のモデルは何でもいいわけで、わざわざ動作が分かりづらいモデルを表示しなくてもいいのだよな…。
RigidBody3D で作ったボールが、StaticBody3Dで作った地面の上をいつまでも転がり続けて悩んでる。どうにかして、どこかのタイミングでピタリと止めたい。RigidBody3D の設定で解決できないものかと調べてた。
とりあえず分かった点をメモしておく。
余談。ボールを球のままにしておくと回転具合がさっぱり分からなかったので、試しに球を箱にしてみたところ、回転具合が分かりやすくなった。コリジョンさえ球になっていれば、見た目のモデルは何でもいいわけで、わざわざ動作が分かりづらいモデルを表示しなくてもいいのだよな…。
◎ 質量を指定 :
mass を指定すると、質量(重さ)をkg単位で指定できる。デフォルトは 1kg になっていた。
以下のページによると、ゴルフボールは 45.93グラムらしいので、mass に 0.045 を指定してみた。今までと同じ力で撃ち出したらとんでもない速度で飛んでいった…。
_ゴルフボールの基礎知識 | ボール | DUNLOP GOLFING WORLD
ただ、この値を弄っても、ボールは相変わらず地面の上をいつまでも転がり続けてしまった。
以下のページによると、ゴルフボールは 45.93グラムらしいので、mass に 0.045 を指定してみた。今までと同じ力で撃ち出したらとんでもない速度で飛んでいった…。
_ゴルフボールの基礎知識 | ボール | DUNLOP GOLFING WORLD
ただ、この値を弄っても、ボールは相変わらず地面の上をいつまでも転がり続けてしまった。
◎ スリープ状態を有効にする :
Deactivation の Can Sleep を有効にしておくと、ある程度動きが小さくなったらスリープ状態になってくれる。おそらく、スリープ状態になれば、動きもピタリと止まるのかなと思うけど、これがなかなかスリープ状態にならない…。
スリープ状態かどうかは、スクリプト内で sleeping という変数を見るか、もしくは is_sleeping() という関数で調べればわかる。true か false が入る。
スリープ状態の変更は、set_sleeping(value: bool) だろうか。ただ、スリープ状態に設定しても、状況によってはスリープが自動で解除される。
スリープより強力な freeze というのもある。これが有効になると完全にその場で静止する。重力も、力も、反映されない。空中に居ても平気で静止する。モード(FreezeMode)によっては他のオブジェクトと衝突もしなくなる、とドキュメントには書いてあった。
スリープ状態かどうかは、スクリプト内で sleeping という変数を見るか、もしくは is_sleeping() という関数で調べればわかる。true か false が入る。
スリープ状態の変更は、set_sleeping(value: bool) だろうか。ただ、スリープ状態に設定しても、状況によってはスリープが自動で解除される。
スリープより強力な freeze というのもある。これが有効になると完全にその場で静止する。重力も、力も、反映されない。空中に居ても平気で静止する。モード(FreezeMode)によっては他のオブジェクトと衝突もしなくなる、とドキュメントには書いてあった。
◎ 移動/回転速度の減衰率 :
Damp という項目は、減衰率を指定できるらしい。減衰率を指定すれば、動いているうちに自然と速度が減っていくようになる。
Linear Damp と Angular Damp は、プロジェクト設定 → 物理 → 3D、でもデフォルト値が設定されている。Default Linear Damp が 0.1、Default Angular Damp が 0.1 になっていた。
Damp Mode が Combine になっていると、プロジェクト設定の Damp値と、RigidBody3D のDamp値を加算した値を実際のDamp値として使う、とドキュメントに書いてあった気がする。デフォルトでは、RigidBody3D 側の Damp値は 0 なので、プロジェクト設定の Damp値がそのまま反映されるのだろう。
Damp Mode が Replace なら、RigidBody3D の Damp値で置き換えてしまうので、プロジェクト設定のDamp値は無視される。
ただ、この Linear/Angular Damp は、RigidBody3D が空中を飛んでる時も反映されてしまうようで…。いやまあ、空気抵抗があると考えたらそのほうが自然なのかな…?
しかし、何かに衝突した時に、移動速度や回転速度がガツンと減ってほしい気もする…。
- Linear → Damp を指定すると、移動速度の減衰率を指定できる。
- Angular → Damp を指定すると、回転速度の減衰率を指定できる。
Linear Damp と Angular Damp は、プロジェクト設定 → 物理 → 3D、でもデフォルト値が設定されている。Default Linear Damp が 0.1、Default Angular Damp が 0.1 になっていた。
Damp Mode が Combine になっていると、プロジェクト設定の Damp値と、RigidBody3D のDamp値を加算した値を実際のDamp値として使う、とドキュメントに書いてあった気がする。デフォルトでは、RigidBody3D 側の Damp値は 0 なので、プロジェクト設定の Damp値がそのまま反映されるのだろう。
Damp Mode が Replace なら、RigidBody3D の Damp値で置き換えてしまうので、プロジェクト設定のDamp値は無視される。
ただ、この Linear/Angular Damp は、RigidBody3D が空中を飛んでる時も反映されてしまうようで…。いやまあ、空気抵抗があると考えたらそのほうが自然なのかな…?
しかし、何かに衝突した時に、移動速度や回転速度がガツンと減ってほしい気もする…。
◎ 衝突してる何かの数を調べる :
Solver → Contact Monitor を有効にすることで、何かと衝突してるかどうかを ―― RigidBody3D と衝突してるポリゴンの枚数を調べることができるようになる。たぶん。ちょっと自信無し。
Contact Monitor を有効にすると Max Contacts Reported という設定項目が増える。ここで指定した数だけ、衝突しているポリゴン枚数を返してくれるので、0 より大きい値を指定しておく。0 が入っていると、衝突枚数として常に 0 しか返ってこない。
スクリプト内では、get_contact_count() を使って衝突個数/枚数を調べることができる。何も当たってなければ0、ポリゴン1枚と当たってたら1、ポリゴンとポリゴンの境界をウロウロしていたら2が返ってきた。3や4が返ってくる時もあるのだろうか?
get_contact_count() を使って、空中に居るのか、地面の上に居るのかを判別できそうな気がする…。0 なら何も当たってないから空中に居る。1以上なら地面のどこかに当たってる。
そして、地面の上に居る時だけ、移動速度と回転速度を減らしてやれば、転がり続ける状態は回避できるのではないか…?
Contact Monitor を有効にすると Max Contacts Reported という設定項目が増える。ここで指定した数だけ、衝突しているポリゴン枚数を返してくれるので、0 より大きい値を指定しておく。0 が入っていると、衝突枚数として常に 0 しか返ってこない。
スクリプト内では、get_contact_count() を使って衝突個数/枚数を調べることができる。何も当たってなければ0、ポリゴン1枚と当たってたら1、ポリゴンとポリゴンの境界をウロウロしていたら2が返ってきた。3や4が返ってくる時もあるのだろうか?
get_contact_count() を使って、空中に居るのか、地面の上に居るのかを判別できそうな気がする…。0 なら何も当たってないから空中に居る。1以上なら地面のどこかに当たってる。
そして、地面の上に居る時だけ、移動速度と回転速度を減らしてやれば、転がり続ける状態は回避できるのではないか…?
◎ 移動速度と回転速度 :
スクリプト内で、移動速度には linear_velocity、回転速度には angular_velocity でアクセスできるらしい。
地面の上に居る時だけ、移動/回転速度をガツンと減らしたいなら、以下のような記述になるだろうか…?
地面の上に居る時だけ、移動/回転速度をガツンと減らしたいなら、以下のような記述になるだろうか…?
@export var vec_damp: float = 0.7 @export var ang_damp: float = 0.3 # ... if get_contact_count() > 0: linear_velocity *= vec_damp angular_velocity *= ang_damp
◎ 状態を画面に表示したい :
RigidBody3D がスリープ状態なのかどうか、あるいは何かと当たっているのか、そういった情報を画面上に表示したい。こんな時は何のノードを使うのだろう?
ググったところ、3D画面の場合でも Labelノードが使えるらしい。
Root の直下に Label を追加。
RigidBody3D のスクリプトで、以下のような感じで記述すればいいのかな。
@export を記述すると、その変数の内容をGUIで変更できるようになる。label という設定項目が増えるから、先ほど追加登録した Label を指定。
Label の .text に文字列を代入してやれば、その文字列が画面に表示される。"\n" で改行を入れれば複数行表示もできる。
GDScript での文字列の変数展開は、Python とちょっと違うらしい…?
ググったところ、3D画面の場合でも Labelノードが使えるらしい。
Root の直下に Label を追加。
RigidBody3D のスクリプトで、以下のような感じで記述すればいいのかな。
@export var label: Label # ... var txt = "hit %d / on ground %f sec\n" % [hit_count, on_ground] txt += "%.6f , %.6f , %.6f\n" % [angular_velocity.x, angular_velocity.y, angular_velocity.z] txt += "%s" % ("sleep" if sleeping else "active") label.text = txt
@export を記述すると、その変数の内容をGUIで変更できるようになる。label という設定項目が増えるから、先ほど追加登録した Label を指定。
Label の .text に文字列を代入してやれば、その文字列が画面に表示される。"\n" で改行を入れれば複数行表示もできる。
GDScript での文字列の変数展開は、Python とちょっと違うらしい…?
- Python ... "Hoge %s %d %f" % ("String", 10, 1.5)
- GDScript ... "Hoge %s %d %f" % ["String", 10, 1.5]
[ ツッコむ ]
#2 [blender] blenderで複数オブジェクトの属性値を一括して変更したい
blender 3.6.18 LTS上で、Drop to Ground というアドオンを使うと、選択オブジェクトを地面等のオブジェクトの上に移動させることができる。杭っぽいモデルを作って、空中にたくさん複製して、Drop to Ground を使ったら、一発で地面の上にたくさんの杭を並べることができた。
ただ、地面の角度が反映されて、各オブジェクトの角度も変わってしまう。角度については 0 にしたい。でも、たくさんあるから手作業ではやってられない。
つまり、複数のオブジェクトを選択して、角度を全部0にしたい。どうすればいいのか…。
以下のページが参考になった。
_「Blender」アトリビュートの一括編集 - Suggypop 3DCG Memo
blender 3.6.18 LTS では、アドオン Copy Atrribute を使えば実現できた。
あるいは、項目の上で右クリックして、以下を選ぶことでも同じことができる。
また、回転をクリアしたいだけなら、Alt + R でもできる。
ただ、地面の角度が反映されて、各オブジェクトの角度も変わってしまう。角度については 0 にしたい。でも、たくさんあるから手作業ではやってられない。
つまり、複数のオブジェクトを選択して、角度を全部0にしたい。どうすればいいのか…。
以下のページが参考になった。
_「Blender」アトリビュートの一括編集 - Suggypop 3DCG Memo
blender 3.6.18 LTS では、アドオン Copy Atrribute を使えば実現できた。
- 複数のオブジェクトを選択。一番最後に選んだオブジェクトがコピー元になる。一番最後に選んだオブジェクトがコピー元になる。大事なことなので2回言いました。
- Ctrl + C でメニューが開く。
- コピーしたいアトリビュート(属性値?)を選べば、選択されている複数のオブジェクトに、コピー元の値をコピーできる。
あるいは、項目の上で右クリックして、以下を選ぶことでも同じことができる。
- 「すべてを選択にコピー (Copy All to Selected)」
- 「一つのみ選択にコピー (Copy Single to Selected)」
- 「選択にコピー (Copy to Selected)」
また、回転をクリアしたいだけなら、Alt + R でもできる。
◎ Alt+クリックは効かなかった :
blenderの昔のバージョンなら Alt + 左クリック、Alt + Enter でも行えたらしい…?
_Blender で複数の要素を一度に変更する
_【Blender】複数オブジェクトを同時にトランスフォームするTips | 謎の技術研究部
_Blender 2.8 複数のオブジェクトの設定を一度にまとめて編集する方法-Suit Dimension Lab
旧バージョンで試したところ、blender 2.83.20 なら Alt + 左クリックを利用できたが、blender 2.93.18 - 4.2.4 では利用できなかった。
Alt + Enter はどのバージョンでも利用できたが、これは現在値に変化後の相対値を加算する処理に見えた。値を入力値で置き換えるわけではないらしい。
_Blender で複数の要素を一度に変更する
_【Blender】複数オブジェクトを同時にトランスフォームするTips | 謎の技術研究部
_Blender 2.8 複数のオブジェクトの設定を一度にまとめて編集する方法-Suit Dimension Lab
旧バージョンで試したところ、blender 2.83.20 なら Alt + 左クリックを利用できたが、blender 2.93.18 - 4.2.4 では利用できなかった。
Alt + Enter はどのバージョンでも利用できたが、これは現在値に変化後の相対値を加算する処理に見えた。値を入力値で置き換えるわけではないらしい。
[ ツッコむ ]
以上、1 日分です。