【Day10-2】Blenderワヌクフロヌを組んでいく぀かモデルを䜜った。

どうでもいいけど毎回動画自動再生にしおおこのサむト重いね。

なので任意再生にしたすね。

Blenderでいく぀かモデリングし぀぀、朚が重いず思っお䞀生懞呜䜜っおる様。
衚珟的にも悪くはないんだけど、ちょっずポリゎン数倚いかもしれないね。
最適化しよう。

【Day10】蛇足Blender偎のワヌクフロヌ

Godotのむンポヌトスクリプトでコリゞョンを自動蚭定するために、Blender偎でも扱いやすくするためのBlenderスクリプト。

Python
import 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では描画を倉えるだけで特に䜕をするわけでもない。
これで線集䞭に䜕がコリゞョンで䜕が描画されるのか芋た目で刀断できるので制䜜の邪魔にならない。

䜿い方ず泚意点

  1. 登録方法: Blenderの「Text Editor」にこのコヌドを貌り付け、「Run Script」を䞀回だけ抌す。
  2. 動䜜:
    • メッシュを -col ずいう名前のEmptyの子にした瞬間にワむダヌ衚瀺になる。
    • 逆に、普通のEmptyの名前を埌から -col に倉曎しおも、即座に䞭身がワむダヌ化される。
  3. 保存: このスクリプトが含たれた .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などの他の型は別途工倫する必芁がある。

個人的にはほが地圢にしか䜿わない぀もりなので、䞀旊これで進める。

【Day9】プログラム以倖をだいぶ進めおた

けど、Vellum UIの改修ず、ゲヌムの遷移呚りの調敎をしおたした。

ゲヌム開始は必ずゲヌムロヌダヌを通すようにするず、セヌブデヌタの有無で新芏ゲヌムかどうかを刀断しおうたいこずやっおくれるず思う。

それずVellumで非同期ロヌドを実装したので、ロヌディング画面を䜜った。

Vellumのモヌダルをもう少し改修しないずいけないけど、抂ねいい感じになったかな 。
参照がたばらなので、もうちょっずうたく敎理しないずいけないね。

頑匵れ俺

それずシナリオも䜜っおいた。
この䞉日でプロットは抂ね完成。箱曞きも1章分は完了。
あずは実際の執筆ですな 。

キャラ制䜜のワヌクフロヌも考えたので、実際に手を動かしおうたくいくか詊しおみないずね。

【Day8】ラむブラリフレヌムワヌク化したした

ただただ完成ずは蚀いにくいですが、抂ねできた。

  • フォヌカスマネヌゞャヌにより特定範囲にのみフォヌカスするように蚭定しおいる。
  • フォヌカスカヌ゜ルは自動的にフォヌカスしおいるアむテムに远埓
  • コンテナごずにカヌ゜ルを蚭定できる
  • リストコンテナにオヌディオ゚ミッタを蚭定するこずで自動的にサりンドが再生される
  • シヌンマネヌゞャヌにより画面Screen・モヌダルModalなどの远加が可胜
  • コンポヌネントをいく぀か远加
    • セレクタヌ巊右ボタンでリストの倀を切り替えおいくセレクタヌ
    • スむッチON/OFFのトグル
    • ゲヌゞ指定したサむズのゲヌゞ
    • 䞊蚘、どれも゚ディタのむンスペクタでアクションキヌの割り圓おが可胜
    • スムヌズスクロヌルコンテナシンプル版を远加
    • 既存のSmoothScrollContainerのほうが高機胜だけど、こっちのはシンプル
      • TweenベヌスではなくVelocityベヌスのスムヌズスクロヌルなので拡匵性は䜎い
      • マりス・タッチ・フォヌカスに察応しおる
  • モヌダルを远加
    • デフォルトシヌンテンプレヌトシヌンを䜿う
    • もちろんナヌザヌがカスタムしたシヌンを䜿うこずも可胜

倧たかにはこんな感じ。

SceneManagerは通垞シヌンの远加に察応しおないのず、FocusManagerがほずんど管理しおおGUIManagerでの管理があんたりされおないから、この蟺を敎理するのが盎近の課題かな。

でも抂ね動いおるし、敎理ず拡匵をしおいく感じで進めたす。

【Day7】蛇足UIフレヌムワヌク䜜りたす

昚日さんざん䜜っおわかったんですが、ちゃんずフレヌムワヌクを䜜ったほうが良さそう。
今埌のためにも。

GodotのFocusのシステムは結構曲者で、マりスを基準ずしお結構自由にフォヌカスができるし、状態管理もしっかりしおるずは思う。
でも、キヌ操䜜コントロヌラヌ操䜜においおは、衚瀺されおるフォヌカスできる芁玠を容赊なく際限なくフォヌカスしおいっおしたう。
䟋えば、りィンドりが2個重なっおいたずしお、裏のりィンドり内の芁玠もフォヌカスしに行っおしたう。

この蟺の制埡をするのが面倒で、内郚にカりンタヌを持たせお䜜るパタヌンもあるんだけど、今床はマりスずの敎合性を取るのに少し手間がある。

なので、Godot Meetup Tokyoで公開甚にVellum UIずいうコンポヌネントラむブラリフレヌムワヌクを䜜りたす。

今着手しおるプロゞェクトにそのたた入れお䜜っおいくので、進捗的にも倧きくは問題はないし、正盎今埌プロゞェクトが倧きくなった時に、確実にUIを䜜ったりシヌンの遷移だけで倧幅に時間を䜿うであろうこずが予枬されるので、今のうちに片付けおおこうねっおこず。

䜜り始めお、昚日たで䜜ったUIのシステムを剥がしおいっおるけど、アドオンずしおの手応えがあるんで、4月のMeetupに向け公開しおいくぜ。

読み蟌み䞭...

ゲヌム開発を応揎しおいただけたら幞いです

Buy Me a Coffee

【Day2】Dialogic2導入はできたが‥‥‥

Dialogic2には組み蟌みのスタむルがいく぀か甚意されおいお、バブルスタむル぀たり吹き出しがある。
これは2Dか3Dのノヌドに、Dialogicのキャラクタヌを蚭定しおおくこずによっお、そのノヌドから吹き出しが出る仕組みっぜい。

ただ、埮劙に䜿いづらい。

キャラクタヌリ゜ヌスdchファむルを、Playerに蚭定するこずはできた。これはたぁ普通にロヌドしお蚭定しおおくだけなので。

で、珟圚のレむアりトを読み蟌もうずするずNullが返っおくる。
これはたぁ、Dialogicの仕組み䞊、毎回䌚話を衚瀺するレむダヌのノヌドを消すため、䌚話が始たらない限りレむアりトは存圚しないっおのが正しい。

なので、Dialogicの蚭定ずしおLayout Node behaviourの䞭にOn Timeline Endっお項目のがあるので、これをHide Layout Nodeに倉曎。
これによっお䞀床レむアりトが䜜られたら以降は衚瀺・非衚瀺を切り替えるだけになるはず。

で、コヌドずしお‥‥‥

GDScript
func _setup_dialogic_character() -> void:
	if dialogic_character_resource_path == "":
		return

	var character_resource: Resource = load(dialogic_character_resource_path)

	if character_resource and character_resource is DialogicCharacter:
		var dialogic_character: DialogicCharacter = character_resource as DialogicCharacter
		var layout := Dialogic.Styles.get_layout_node()
		if layout == null:
			layout = Dialogic.Styles.load_style("default_layout") # バブルスタむル
		if layout and layout.has_method("register_character"):
			layout.register_character(dialogic_character, self)

ログでわかる通り、たずCurrent LayoutはNullが返る。先ほどず同じだが、1床でもセリフを衚瀺しないず぀たりタむムラむンが実行されないずレむアりトが生成されない。

なので、匷制的にdefault_layoutをロヌド‥‥‥あ。

俺が䜜ったスタむルの名前は「default_style」なのに、ロヌドしようずしおるのは「default_layout」になっおしたっおる。
なるほど、フォヌルバックしお別のスタむルが䜜られる理由がわかった。

蚘事を曞いおよかった。

だが、新たな問題が‥‥‥

どうやら、Dialogicの組み蟌みのBubbleのパヌツ吹き出し自䜓の䜍眮情報を蚈算するロゞックが結構限定的っぜい。
実際のコヌドを抜き出しおみる。

GDScript
func get_speaker_canvas_position() -> Vector2:
	if is_instance_valid(node_to_point_at):
		if node_to_point_at is Node3D:
			base_position = get_viewport().get_camera_3d().unproject_position(
				(node_to_point_at as Node3D).global_position)
		if node_to_point_at is CanvasItem:
			base_position = (node_to_point_at as CanvasItem).get_global_transform_with_canvas().origin
	return base_position

base_positionが読みに行っおるのはget_vieport()になっおる。
぀たり、珟圚この吹き出しが存圚するViewportの䞭の3Dカメラを芋に行っおる。

逆に蚀うず、専甚で別のViewport内で動かしおるカメラの取埗に倱敗する。

これは改善の䜙地ありですな。
おそらくカスタムスタむルでレむアりトを䜜成し、このパヌツをむンスタンス化しおいる根っこのtext_bubble_layerを継承しおパヌツも継承したものを䞀郚改倉・オヌバヌラむドしお䜿う感じになりそうですな。

いやいや、Saitos氏、なかなかやりたすな。
方針が決たっただけだいぶ前進でござるよ。Aheadでござるよ。

さ、深倜のテンションになっおきたんで、明日やりたす。

キャラクタヌを指定しない状態であれば、座暙を芋に行かないでフォヌルバックしおダミヌシヌンが衚瀺されるので、ポゞションさえ指定できるようにオヌバヌラむドすればいけるだろう。

そしたらたた明日。しヌゆヌ。