ラベル Godot の投稿を表示しています。 すべての投稿を表示
ラベル Godot の投稿を表示しています。 すべての投稿を表示

2025-07-19 godot 4.4.1 でアドベンチャーゲーム(ADV)のセリフを表示する枠・欄のようなものをざっくりと作る

godot で作るゲームの画面にメッセージを出すために、メッセージボックス的なものがほしいと思いました
第三者が公開されているアドオンで「Dialogなんとか」がボチボチあるけど、godot のバージョンアップに追随しているかわからなく、そのアドオンの使い方を理解するための学習コストと自作のコストが釣り合わないと感じました
2D 3D 両方で使えるものをざっくり作ります
yes/no のように選択できるボタンも内包します
作成メモを残します

シーン(scene)内に、ツリーを作ります
何とかscene
  CanvasLayer
    MessageBox  ←Control を作って、名前を「MessageBox」にします
      Panel
        Label
        ButtonYes
        ButtonNo  ←Button を2つ作って、名前を「ButtonYes」「ButtonNo」にします
パラメータは .gd スクリプトで設定するので、ザクザクとツリーを作ります

MessageBox 行の横に紙・スクリプトのアイコンがついていますね
message_box.gd を紐付けて動作させます
大きさや色は message_box_styler.gd で設定します
#---- message_box.gd ----#
extends Control

@onready var label = $Panel/Label
@onready var button_yes = $Panel/ButtonYes
@onready var button_no = $Panel/ButtonNo

var yes_callback: Callable = func(): pass
var no_callback: Callable = func(): pass

var _on_buttonYes_pressed: Callable = func(): pass
var _on_buttonNo_pressed: Callable = func(): pass

# サイズ・色などを直接設定する関数
func set_box_style_custom(box_size: Vector2, box_position: Vector2, bg_color: Color, text_color: Color):
	$Panel.size = box_size
	$Panel.position = box_position

	var style_box := StyleBoxFlat.new()
	style_box.bg_color = bg_color
	style_box.corner_radius_all = 8
	$Panel.add_theme_stylebox_override("panel", style_box)

	$Panel/Label.add_theme_color_override("font_color", text_color)

# プリセットスタイルを適用する関数
func set_box_style(style: String = "default"):
	match style:
		"title":
			MessageBoxStyler.apply_title_style(self)
		_:
			MessageBoxStyler.apply_default_style(self)

###func show_message(text: String, on_yes: Variant = null, on_no: Variant = null):
func show_message(
	text: String,
	on_yes: Variant = null,
	on_no: Variant = null,
	yes_text: String = "Yes",
	no_text: String = "No"
):
	if label == null:
		push_error("x label が null です。ノード 'Panel/Label' を確認してください")
	else:
		label.text = text
	visible = true

	button_yes.visible = on_yes != null
	button_no.visible = on_no != null
	button_yes.text = yes_text
	button_no.text = no_text

	yes_callback = on_yes if on_yes != null else func(): pass
	no_callback = on_no if on_no != null else func(): pass


	yes_callback = on_yes if on_yes != null else func(): pass
	no_callback = on_no if on_no != null else func(): pass

func _on_button_yes_pressed():
	visible = false
	yes_callback.call()

func _on_button_no_pressed():
	visible = false
	no_callback.call()

func _ready():
	hide()
	# o シグナルが接続されていない場合に備えて接続
	$Panel/ButtonYes.pressed.connect(_on_button_yes_pressed)
	$Panel/ButtonNo.pressed.connect(_on_button_no_pressed)
	# デフォルトボタン動作
	_on_buttonYes_pressed = func(): pass
	_on_buttonNo_pressed = func(): pass

func _on_ButtonYes_pressed():
	_on_buttonYes_pressed.call()

func _on_ButtonNo_pressed():
	_on_buttonNo_pressed.call()

func set_button_texts(text1: String, text2: String):
	if $ButtonYes and $ButtonNo:
		$ButtonYes.text = text1
		$ButtonNo.text = text2
	else:
		push_error("x ButtonYes または ButtonNo が見つかりません")

func set_callbacks(callback1: Callable, callback2: Callable):
	_on_buttonYes_pressed = callback1
	_on_buttonNo_pressed = callback2
# ---- message_box.gd ここまで ----#


#---- message_box_styler.gd ----#
class_name MessageBoxStyler

static func apply_title_style(box: Control):
	assert(box != null)
	var panel := box.get_node("Panel")
	panel.size = Vector2(800, 400)
	panel.position = Vector2(500, 300)
	panel.modulate = Color(2, 2, 2, 0.8)

	var stylebox := StyleBoxFlat.new()
	stylebox.bg_color = Color(0.1, 0.1, 0.1, 0.6)
	stylebox.border_width_bottom = 2
	stylebox.border_color = Color(1, 1, 0)
	panel.add_theme_stylebox_override("bg", stylebox)

	var label := box.get_node("Panel/Label")
	if label.label_settings == null:
		label.label_settings = LabelSettings.new()

	label.label_settings.font_size = 48
	label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
	label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER

	var button_yes := box.get_node("Panel/ButtonYes")
	var button_no := box.get_node("Panel/ButtonNo")

	button_yes.size = Vector2(400, 50)
	button_yes.position = Vector2(100, 160)
	button_yes.text = "Yes"

	button_no.size = Vector2(400, 50)
	button_no.position = Vector2(100, 260)
	button_no.text = "No"

	button_yes.size_flags_horizontal = 0
	button_no.size_flags_horizontal = 0

	###var font_settings := LabelSettings.new()
	###font_settings.font_size = 36

	# Yes ボタン
	button_yes.text = "Yes"
	button_yes.add_theme_font_size_override("font_size", 24)
	button_yes.add_theme_color_override("font_color", Color(0, 0, 0, 1.0)) # 黒文字

	var yes_style := StyleBoxFlat.new()
	yes_style.bg_color = Color(0.4, 0.9, 0.4, 1.0) # 緑
	button_yes.add_theme_stylebox_override("normal", yes_style)

	# No ボタン
	button_no.text = "No"
	button_no.add_theme_font_size_override("font_size", 24)
	button_no.add_theme_color_override("font_color", Color(0, 0, 0, 1.0))

	var no_style := StyleBoxFlat.new()
	no_style.bg_color = Color(0.9, 0.4, 0.4, 1.0) # 緑
	button_no.add_theme_stylebox_override("normal", no_style)

	print("ButtonNo pos: ", button_no.position)
	print("ButtonNo size: ", button_no.size)
	print("Panel size: ", panel.size)

	# --- パネルが画面外にはみ出ないように調整 ---
	var screen_size = box.get_viewport().get_visible_rect().size

	# パネルのサイズが大きすぎたら調整
	panel.size.x = min(panel.size.x, screen_size.x - 20)
	panel.size.y = min(panel.size.y, screen_size.y - 20)

	# パネルの位置がはみ出していたら調整
	if panel.position.x + panel.size.x > screen_size.x:
		panel.position.x = screen_size.x - panel.size.x - 10
	if panel.position.y + panel.size.y > screen_size.y:
		panel.position.y = screen_size.y - panel.size.y - 10

	# 画面外に飛びすぎていたら 0 に制限(逆方向)
	panel.position.x = max(panel.position.x, 10)
	panel.position.y = max(panel.position.y, 10)



static func apply_default_style(box: Control):
	assert(box != null)
	var panel := box.get_node("Panel")
	panel.size = Vector2(800, 240)
	panel.position = Vector2(100, 500)
	panel.modulate = Color(0, 0, 0, 0.8)

	var stylebox := StyleBoxFlat.new()
	stylebox.bg_color = Color(0.1, 0.1, 0.1, 0.6)
	stylebox.border_width_bottom = 2
	stylebox.border_color = Color(1, 0, 0)
	panel.add_theme_stylebox_override("bg", stylebox)

	var label := box.get_node("Panel/Label")
	if label.label_settings == null:
		label.label_settings = LabelSettings.new()
	label.label_settings.font_size = 24
	label.horizontal_alignment = HORIZONTAL_ALIGNMENT_LEFT
	label.vertical_alignment = VERTICAL_ALIGNMENT_CENTER

	panel.modulate = Color(1, 1, 1, 1) # ← 透明度の影響を排除

	var button_yes := box.get_node("Panel/ButtonYes")
	var button_no := box.get_node("Panel/ButtonNo")

	# Yes ボタン
	button_yes.text = "Yes"
	button_yes.add_theme_font_size_override("font_size", 24)
	button_yes.add_theme_color_override("font_color", Color(0, 0, 0, 1.0)) # 黒文字

	var yes_style := StyleBoxFlat.new()
	yes_style.bg_color = Color(0.4, 0.9, 0.4, 1.0) # 緑
	button_yes.add_theme_stylebox_override("normal", yes_style)
	button_yes.position = Vector2(100, 120)

	# No ボタン
	button_no.text = "No"
	button_no.add_theme_font_size_override("font_size", 24)
	button_no.add_theme_color_override("font_color", Color(0, 0, 0, 1.0)) # 黒文字

	var no_style := StyleBoxFlat.new()
	###no_style.bg_color = Color(1.0, 0.5, 0.6, 1.0) # ピンク寄り赤
	no_style.bg_color = Color(0.4, 0.9, 0.4, 1.0) # 緑
	button_no.add_theme_stylebox_override("normal", no_style)
	button_no.position = Vector2(50, 60)

	print("ButtonNo pos: ", button_no.position)
	print("ButtonNo size: ", button_no.size)
	print("Panel size: ", panel.size)

	# --- パネルが画面外にはみ出ないように調整 ---
	var screen_size = box.get_viewport().get_visible_rect().size

# パネルのサイズが大きすぎたら調整
	panel.size.x = min(panel.size.x, screen_size.x - 20)
	panel.size.y = min(panel.size.y, screen_size.y - 20)

	# パネルの位置がはみ出していたら調整
	if panel.position.x + panel.size.x > screen_size.x:
		panel.position.x = screen_size.x - panel.size.x - 10
	if panel.position.y + panel.size.y > screen_size.y:
		panel.position.y = screen_size.y - panel.size.y - 10

	# 画面外に飛びすぎていたら 0 に制限(逆方向)
	panel.position.x = max(panel.position.x, 10)
	panel.position.y = max(panel.position.y, 10)
#---- message_box_styler.gd ここまで ----#


呼び出す側のスクリプトに @onready と show_message() を書いていきます
show_message の前に set_box_style("title") を書くことでタイトル画面で使えるような、画面中央で大きめのメッセージボックスを出せるようにしてます
下記はシーン(3dNode)にスクリプトを直接紐付けて呼び出すサンプルです
#---- secene_0000.gd ----#
extends Node3D

@onready var msgbox = $world/CanvasLayer/MessageBox
###@onready var player = $world/Player  # player の取得も必要ならここで

func _ready():
	msgbox.set_box_style("title")
	msgbox.show_message("This is GAME.  start game?",
		func():
			###player.enabled = true
			print("o YES select. move scene")
			get_tree().change_scene_to_file("res://scene/_scene_0001/scene_0001.tscn"),
		func():
			###player.enabled = true
			print("No select..."),
		"Start Game",
		"No Game"
	)
	
#---- scene_0000.gd ----#
以下にスクリーンショットつけます

ボタンを押すと遷移しました



2025-02-26 vroid studio → blender → mixamo → godot

Blender に VRM ファイルを取り込む前に、
右シーンコレクション内の「シンコレクション」以下を全て削除
上部メニューの「ファイル」「インポート」「VRM (.vrm)」を選択し vrm
ファイルを取り込む VRM取り込み後、 ICO球を削除(見当たらなければ放置)
glTF_not_exportedを削除(見当たらなければ放置) オレンジ色のArmatureを展開
緑色のArmatureを展開
ウィンドウ上部のメニュー欄の「レイアウト」を選び「オブジェクトモード」にする
左の人物が表示されている枠内で何かボーンをクリックしオレンジ色にする
左上の「オブジェクトモード」を「編集モード」にする
右シーンコレクション内の「Root」以下を展開
右シーンコレクション内の「Root」だけを選択 左ステージ内にマウスを動かして delete
キー(Rootのボーンを削除)
ウィンドウ上部のメニュー欄の「Scripting」を選ぶ(かなり右側にある) 「+
新規」を押す。 下記のスクリプトを貼り付け 右上の実行ボタンを押す


#---------- スクリプトここから ----------
import bpy

for x in bpy.context.object.data.bones:
    x.name = x.name.replace("J_Bip_C_", "mixamorig:")
    x.name = x.name.replace("J_Bip_L_", "mixamorig:Left")
    x.name = x.name.replace("J_Bip_R_", "mixamorig:Right")
    x.name = x.name.replace("LeftUpper", "LeftUp")
    x.name = x.name.replace("RightUpper", "RightUp")
    x.name = x.name.replace("mixamorig:Chest", "mixamorig:Spine1")
    x.name = x.name.replace("mixamorig:UpperChest", "mixamorig:Spine2")
    x.name = x.name.replace("LowerLeg", "Leg")
    x.name = x.name.replace("LowerArm", "ForeArm")
    x.name = x.name.replace("UpArm", "Arm")
    x.name = x.name.replace("LeftIndex", "LeftHandIndex")
    x.name = x.name.replace("LeftThumb", "LeftHandThumb")
    x.name = x.name.replace("LeftRing", "LeftHandRing")
    x.name = x.name.replace("LeftMiddle", "LeftHandMiddle")
    x.name = x.name.replace("LeftLittle", "LeftHandPinky")
    x.name = x.name.replace("RightIndex", "RightHandIndex")
    x.name = x.name.replace("RightThumb", "RightHandThumb")
    x.name = x.name.replace("RightRing", "RightHandRing")
    x.name = x.name.replace("RightMiddle", "RightHandMiddle")
    x.name = x.name.replace("RightLittle", "RightHandPinky")

#---------- スクリプトここまで ----------


右シーンコレクション内の
緑色のArmatureを展開、名前を変更する際に狭く
見えにくいので、右シーンコレクションを広げておくことを推奨


ウィンドウ上部のメニュー欄の「レイアウト」を選び「編集モード」にする
足の指にあたるボーン(丸豆だけでなく三角錐)をクリックし選択状態にして、
そのボーンを右クリックして「細分化」
(足の左右を実施する)

右上の 緑色のArmatureを展開していき
細分化した、「mixamorig:LeftToeBase.00?」を「mixamorig:LeftToe_End」にリネーム
細分化した、「mixamorig:RightToeBase.00?」を「mixamorig:RightToe_End」にリネーム

######## ここまで必須 ########
######## 手の指関節追加は任意 ########
手の指にあたるボーン(丸豆だけでなく三角錐)をクリックし選択状態にして、
そのボーンを右クリックして「細分化」
(左右の手を実施する)

右上の 緑色のArmatureを展開していき
細分化した、「mixamorig:***3.001」を「mixamorig:***4」にリネーム
任意の指の数だけ実施

######## 手の指関節追加は任意ここまで ########



右シーンコレクション内の「シーンコレクション」配下に
「コレクション」を一段作り、その中に
コライダー(Colliders)やら Armature やら Body や Face 等
すべて移動
「コレクション」のプルダウンを閉じる

右シーンコレクション内の「シーンコレクション」配下に
「コレクション」を一段作り、その中に
fbx ファイルをインポートする。
アドオンの「Rokoko」のメニューを出す

rokokoを使わないバージョンもあります。


「Retargeting」のプルダウンを広げる
ソース: に、今読み込んだ方の Armature(たぶん 001 が付いている)を選ぶ
ターゲtット: に、もともとの Armature(たぶん無印)を選ぶ
「Build Bone List」のボタンを押す
リストが出るので、左と右に同じ名前が入っているか確認する
たまに、間違えているので注意する。
入ってなければ入れる。
「Retarget Animation」を押したいが、その下の「保存」を押しておくと
次回以降の Bone List が間違いなくなるので「保存」を押しておく
「エクスポート」を押しておくと、Json ファイルが出力できる。(PC故障して交換したとき等は、Jsonファイルを読むと楽なはず)
あと、インポートしたファイルと、モーション適用先のポーズを「REST(T-Poseになるはず)」にして、
モーションの左右向き、上下向きを合わせておかないとおかしなモーションを取り込むことがある。
「Retarget Animation」を押す。


ウィンドウ上部のメニュー欄の「アニメーション」を選ぶ
ウィンドウ下部の左隅にある菱形のマークを含む模様(アイコン?)
の1マスのプルダウンを展開し、
ノンリニアアニメーションを選択する
もともとの Armature(たぶん無印)の直下にあるオレンジ行の
「~~ Retarget」の横にある、下向き三角と四角2個が書いてあるアイコンをクリックする
<アクションなし>が増える
<アクションなし>の真下の行の名前を、今読み込んだ行動の任意名称に変更しておく。
これで読み込まれたはず

<アクションなし>をクリックし右の方に出た
「新規」の左隣の菱形のマークを含む模様(アイコン?)をクリックする
「~~ Retarget」を選択する。
右シーンコレクション内に追加していたコレクションを
丸ごと削除する
Armature.001 のようなものが残ったら、それも削除する

また、右シーンコレクション内の「シーンコレクション」配下に
「コレクション」を一段作り、その中に
fbx ファイルをインポートする~~を繰り返す

blender は vrm ではなく glb 出力
glb 出力する前に、
ウィンドウ上部のメニュー欄の「レイアウト」を選び「オブジェクトモードにして」
キャラクターがいる欄の何もないところを一旦クリックし
「a」キーを押して全選択状態にしてからエクスポートする


顔の表情をシェイプキーの設定の情報だけの状態ではなく、
Armature(オレンジ色) のアニメーションと同等に、godot 内から
アニメーションとして扱いやすくする方法が下記。
(godot で作る内容次第なので必須ではない)

右シーンコレクション内の「シーンコレクション」配下に
下向き三角形(オレンジ色)の「Face」の選択状態にし、
ウインドウ右下のいろんなアイコンが縦に並んでいるタブの
緑いろの下向き三角形を選び
「アニメーション」の欄を展開して、シェイプキーの下にある「+ 新規」を押す
任意の名前を付ける(今回は d-eyes-closeとする)、
その入力欄の右にある2重の四角形(新規アクション)のボタンを押す


ウィンドウ上部のメニュー欄の「アニメーション」を選ぶ
ウィンドウ下部の左隅にある菱形のマークを含む模様(アイコン?)
の1マスのプルダウン(アイコン?)を展開し、
「ドープシート」を選択する。
その1マスのプルダウン(アイコン?)の右隣のプルダウンは
「シェイプキーエディター」を選択する
その下にタイムラインのようなものと、「概要」を展開すると
Fcl_~みたいなリストが並んでいるはず。
0.000 から 1 に変えることで、設定済の表情(顔の部位の変更)ができる
(今回は、Fcl_EYE_Close を 0.000 から 1 に変える)
先ほど、「シェイプキーエディター」を選択したやや右に
「ストリップ化」があるので押す


顔の表情を増やしたい場合は、
右シーンコレクション内の「シーンコレクション」配下に
下向き三角形(オレンジ色)の「Face」の選択状態にするところから繰り返す。
(ちなみに、表情を増やしたい (NLAトラックが増えていきます) 場合は、
「シェイプキーエディター」で変更したままの状態(表情)になっているので、
新規の表情を作るときは、前の表情を戻すことを実施)

glb の出力
出力方法は、「レイアウト」タブにして「オブジェクトモード」、
左枠内の何もないところでクリック後に「a」で選択した状態でエクスポート。

Animation を godot に取り込む方法(.resファイルにする)までは一緒
.res を取り込んだ後に、AnimationPlayer で、
表情の Animation についている「顔以外の動作」(T-Pose)になっていると思うが
Animation のトラック内に表示されている、〼 Face 配下の「緑丸 Fcl_~」は残し、
「Skeleton3D」配下の 赤紫マークから始まるの mix~ だったり
茶色十字からはじまる行は削除(ゴミ箱マークをクリック)しましょう
目を閉じるアニメーション等、表情が変わるアニメーションを選んで、表情が変わることを確認したあとに、
ジャンプなどのアニメーションをえらんで、表情が戻ることなくそのままでジャンプなどの動作を
実施していることを確認する

2024-06-30 Godot で Starter-Kit-FPS をダウンロードして取り込み、debug/編集できるようにするメモ

Godot(ゴドーと読むっぽい)の使い方がいくつか紹介されているが、Starter-Kit-FPS について日本語で書かれている記事がないようだ。 未来の自分向けにメモを残すことにする。
まず、Godot を起動する。 Godot のダウンロードやインストールは他の方の紹介ページに任せ省略する。 起動後に「+ 新規」を押して、新しいプロジェクトを作る。
プロジェクト名を入力して、レンダラーは互換性を選びバージョン管理なんとかを適当に選んで「作成して編集」を押す。
プロジェクトのフォルダが出来たので、一旦×で終了。
Kenney 様にて公開されている Starter-Kit-FPS (https://github.com/KenneyNL/Starter-Kit-FPS) をダウンロードする。Github からのダウンロードは他の方の紹介を参考に。 素晴らしいテンプレートを公開されている Kenney 様に感謝!(生活が落ち着いたら寄付します)
ダウンロードしたものを解凍/展開する
解凍/展開したら、中にフォルダがあるのでその中を表示する
ここまで表示したら、邪魔にならないように最小化等で一旦よけておく
godot で作成したプロジェクトの保存先を表示して、中身を全部削除する
Kenney 様が作られたファイル/フォルダを全部コピーして、空にしたプロジェクト内に貼り付ける
ここで、Godot の起動オプションを変えるため、Godot のプログラムを右クリックして godot のショートカットをつくる
作成したショートカットのプロパティを表示する
リンク先の先頭に「"」(半角のダブルクォテーション)を入れ、リンク先の末尾に「" 」(半角のダブルクォテーション&半角スペース)と「 --rendering-driver opengl3」を追記して適用を押し OK を押す
作ったショートカットをダブルクリックで Godot を起動して、先ほどのプロジェクトをダブルクリックする(プロジェクト名が変わっていてもキニシナイ)
Godot4.1 とか Godot4.2 とか聞かれるけど OK を押す
プロジェクトの内容が読み込まれたら、上部メニューの「プロジェクト」を押し「プロジェクト設定...」をクリックする
一般タブの左ツリー内の「レンダリング」>「レンダラー」を選択し、レンダリングメソッドを「gl_compatibility」に変更(プルダウンから選び)保存し Godot を終了/起動する
次回起動は、ショートカットからではなく普通にプログラムから起動/読み込みできるはず
上部右側にある、右向きの▲から実際に動作を確認できる。 以上、完了