Godotのインポートスクリプトでコリジョンを自動設定するために、Blender側でも扱いやすくするためのBlenderスクリプト。
Pythonimport bpy
from bpy.app.handlers import persistent
# 🛡️ ハンドラ関数の定義
@persistent
def auto_setup_collision_viz(scene):
"""
シーンの更新を監視して、-col配下のメッシュを自動でワイヤー表示にする 🕵️
"""
# シーン内の全オブジェクトをループして条件チェック
for obj in bpy.data.objects:
# 親がEmptyであり、かつ名前に "-col" が含まれているか確認 📦
if obj.parent and obj.parent.type == 'EMPTY' and obj.parent.name.endswith("-col"):
# メッシュオブジェクトのみ対象 💎
if obj.type == 'MESH':
# 既に設定済みならスキップして負荷を軽減 ⚡
if obj.display_type != 'WIRE' or not obj.show_in_front:
obj.display_type = 'WIRE'
obj.show_in_front = True
print(f"✨ [Auto] {obj.name} をコリジョン表示に切り替えました 🔧")
# 📋 ハンドラの登録解除(二重登録を防ぐ)
def register():
if auto_setup_collision_viz not in bpy.app.handlers.depsgraph_update_post:
bpy.app.handlers.depsgraph_update_post.append(auto_setup_collision_viz)
print("🚀 コリジョン監視ハンドラを登録しました!")
def unregister():
if auto_setup_collision_viz in bpy.app.handlers.depsgraph_update_post:
bpy.app.handlers.depsgraph_update_post.remove(auto_setup_collision_viz)
print("🛑 コリジョン監視ハンドラを解除しました。")
# 🚀 実行
if __name__ == "__main__":
register()
基本的にはBlenderでは描画を変えるだけで特に何をするわけでもない。
これで編集中に何がコリジョンで何が描画されるのか見た目で判断できるので制作の邪魔にならない。
使い方と注意点
- 登録方法: Blenderの「Text Editor」にこのコードを貼り付け、「Run Script」を一回だけ押す。
- 動作:
- メッシュを
-col という名前のEmptyの子にした瞬間にワイヤー表示になる。
- 逆に、普通のEmptyの名前を後から
-col に変更しても、即座に中身がワイヤー化される。
- 保存: このスクリプトが含まれた
.blend ファイルを保存し、次回開いた時にも自動で有効にしたい場合、テキストエディタのメニューから Text > Register(登録) にチェックを入れる。
次にGodotのインポートスクリプト。
GDScript# 🛠️ カスタム・ブレンダー・インポーター
# 表示オブジェクトを維持しつつ、コリジョンを自動構成します
@tool
extends EditorScenePostImport
func _post_import(scene: Node) -> Object:
_iterate_nodes(scene, scene)
return scene
func _iterate_nodes(node: Node, root: Node):
if node == null:
return
# 🔍 名前が "-col" で終わるノードを検索
if node is Node3D and node.name.ends_with("-col"):
_process_custom_collision(node, root)
# 変換後はこの枝の走査を終える(内部で再構築されるため)
return
for child in node.get_children():
_iterate_nodes(child, root)
func _process_custom_collision(source_node: Node3D, root: Node):
var parent = source_node.get_parent()
if not parent:
return
# 📦 1. 新しい StaticBody3D を作成(ここが表示と物理の親になる)
var static_body = StaticBody3D.new()
static_body.name = source_node.name.replace("-col", "")
static_body.transform = source_node.transform
parent.add_child(static_body)
static_body.owner = root
print("✨ [CustomImport] 物理・表示統合ノードを生成: ", static_body.name)
# 🔄 2. 子ノード(メッシュ等)の処理
for child in source_node.get_children():
# 物理形状 (CollisionShape3D) の生成
if child is MeshInstance3D:
var mesh = child.get_mesh()
if mesh:
# コリジョン形状の作成
var col_shape = CollisionShape3D.new()
col_shape.shape = mesh.create_convex_shape()
col_shape.transform = child.transform
col_shape.name = "Collision_" + child.name
static_body.add_child(col_shape)
col_shape.owner = root
child.get_parent().remove_child(child)
print(" ✅ 物理と表示をセットしました: ", child.name)
# 🗑️ 3. 役割を終えた元の Empty のみを削除
source_node.queue_free()
GodotにはEmptyを自動的にコリジョン形状として扱う機能があるはずなんだけど、だいぶ前から完全に死んでるっぽいので、特定のEmptyの子をすべてコリジョン形状として扱うスクリプトとした。
注意
- コリジョン形状をメッシュそのままを使うので、複雑な形状は重くなる。
- StaticBody3Dしか扱わないようにしてるので、RigidBody3DやArea3Dなどの他の型は別途工夫する必要がある。
個人的にはほぼ地形にしか使わないつもりなので、一旦これで進める。