SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Godot Engine 2Dゲーム開発入門

【Godot Engine 2Dゲーム制作 Part3】タイトル画面を作ってBGMを追加しよう!

Godot Engine 2Dゲーム開発入門 第5回

  • X ポスト
  • このエントリーをはてなブックマークに追加

画面遷移を管理するスクリプトを書こう

グローバル変数

 これまでとは異なることをします。res://singletonフォルダーをまだ作っていない場合は、事前に作ってください。

 まず、「ファイルシステム」ドックのres://singletonフォルダーを右クリックして、「新規作成」>「スクリプト」を選びます。

 「スクリプト作成」ダイアログが開きますので、「テンプレート」のチェックボックスを外し、「パス」をres://singleton/scene_manager.gdにして「作成」ボタンを押します。

 次にトップメニューの「プロジェクト」>「プロジェクト設定」を選び、「プロジェクト設定」ダイアログを開きます。そして「グローバル」タブ>「自動読み込み」タブを表示します。

 「パス」の横にフォルダーのアイコンがあるのでクリックします。そして、作成したres://singleton/scene_manager.gdを選択して、画面右端の「追加」ボタンを押します。そうすると、「名前」が「SceneManager」、「パス」が「res://singleton/scene_manager.gd」という項目が追加されます。

グローバル変数
グローバル変数

 この場所に登録されたスクリプトやシーンは、ゲームが起動した時に自動でインスタンス化されます。そして「名前」を利用して他のスクリプトから利用できます。

 このグローバル変数は、通常のシーンツリーの外に配置されます。そして、シーンが遷移しても削除されず、どのシーンからでも利用可能になります。

 シーンの遷移を管理するスクリプトは、シーンの作成や削除の影響を受けないようにしなければなりません。そのため、scene_manager.gdをグローバル変数として登録して、「SceneManager」の名前で利用可能にします。

画面遷移を管理するスクリプト

 scene_manager.gdをダブルクリックして「Script」ビューで開きます。scene_manager.gdに、次のようにシーン管理をおこなうプログラムを書きます。

scene_manager.gd
extends Node

const TITLE = "res://scn/title/title.tscn"
const MAZE = "res://scn/maze/maze.tscn"
const TRAN_LEAVE = preload("res://scn/transition/transition_leave.tscn")
const TRAN_ENTER = preload("res://scn/transition/transition_enter.tscn")
var first_enter = true


# シーンのロード
func load_scene(path) -> void:
	# 事前読み込み
	ResourceLoader.load_threaded_request(path)
	
	# シーン遷移演出
	print("[load_scene] transition: start")
	var tran_leave = TRAN_LEAVE.instantiate()
	get_tree().get_current_scene().add_child(tran_leave)
	await tran_leave.leave()
	print("[load_scene] transition: end")

	# 読み込み完了するまで待機
	while ResourceLoader.load_threaded_get_status(path) == \
			ResourceLoader.THREAD_LOAD_IN_PROGRESS:
		print("[load_scene] wait load...")
		await get_tree().process_frame

	# シーン切り替え
	get_tree().change_scene_to_packed(ResourceLoader.load_threaded_get(path))


# シーン開始時のシーン遷移演出
func effect_enter_scene() -> void:
	# 初回は無視
	if first_enter:
		first_enter = false
		return

	# シーン遷移演出
	var tran_enter = TRAN_ENTER.instantiate()
	get_tree().get_current_scene().add_child(tran_enter)
	await tran_enter.enter()

 以前のget_tree().change_scene_to_file("res://scn/maze/maze.tscn")より、非常に長くなっています。シーン遷移の演出を加えたり、シーンを読み込むのを待機したり、さまざまな処理をおこなうようにしたためです。

スクリプトの解説1 定数と変数の定義

 冒頭に、いくつかの定数や変数を用意しています。

const TITLE = "res://scn/title/title.tscn"
const MAZE = "res://scn/maze/maze.tscn"
const TRAN_LEAVE = preload("res://scn/transition/transition_leave.tscn")
const TRAN_ENTER = preload("res://scn/transition/transition_enter.tscn")
var first_enter = true

 TITLEMAZEは、今回のゲームに存在しているシーンのパスです。スクリプトの各所でパスを書くのは管理の都合上望ましくないです。そのためSceneManager.TITLEのように、定数で利用可能にします。

 TRAN_LEAVETRAN_ENTERは、先ほど作成した画面遷移の演出シーンです。

 first_enterは「ゲーム開始時だけ画面に入る演出をおこなわない」ためのフラグです。

スクリプトの解説2 load_scene関数

 次はload_scene関数です。ここでは「シーンの事前読み込みと切り替え」と「シーン遷移演出」の2種類の処理が入っています。

 まずは、「シーン遷移演出」の方から解説します。

	# シーン遷移演出
	var tran_leave = TRAN_LEAVE.instantiate()
	get_tree().get_current_scene().add_child(tran_leave)
	await tran_leave.leave()

 TRAN_LEAVEをインスタンス化したあと、get_current_scene関数で現在のシーンツリーのルートを得て、add_child関数で追加します。そして、leave関数を実行してawaitで演出が終わるのを待ちます。

 このシーン遷移演出で画面をフェードアウトしたあと、裏でシーン遷移処理をおこないます。

 次は「シーンの事前読み込みと切り替え」です。

	# 事前読み込み
	ResourceLoader.load_threaded_request(path)
	
	# 読み込み完了するまで待機
	while ResourceLoader.load_threaded_get_status(path) == \
			ResourceLoader.THREAD_LOAD_IN_PROGRESS:
		await get_tree().process_frame

	# シーン切り替え
	get_tree().change_scene_to_packed(ResourceLoader.load_threaded_get(path))

 ResourceLoaderを使って、読み込みを待ったあとにシーン切り替えをおこないます。

 while文のブロック内でawait get_tree().process_frameを使うことで、読み込みが完了するまで待機します。

 読み込み中かは、load_threaded_get_status関数の戻り値がTHREAD_LOAD_IN_PROGRESSなのかで分かります。

 この方法でシーンを切り替える際は、以前出てきたchange_scene_to_file関数ではなく、change_scene_to_packed関数を利用します。

スクリプトの解説3 effect_enter_scene関数

 続いて、effect_enter_scene関数を説明します。

# シーン開始時のシーン遷移演出
func effect_enter_scene() -> void:
	# 初回は無視
	if first_enter:
		first_enter = false
		return

	# シーン遷移演出
	var tran_enter = TRAN_ENTER.instantiate()
	get_tree().get_current_scene().add_child(tran_enter)
	await tran_enter.enter()

 この関数は、シーン開始時の遷移演出をおこないます。この関数は、遷移後のシーンの_ready関数から呼び出します。

 変数first_enterを使い、最初の1回だけは処理をおこなわないようにします。

 2回目以降は、TRAN_ENTERをインスタンス化したあと、get_current_scene関数で現在のシーンツリーのルートを得て、add_child関数で追加します。そして、enter関数を実行してawaitで演出が終わるのを待ちます。

 この後、「Title」と「Maze」シーンにこの関数を書きます。その際は、awaitを書かずにこの関数を実行します。待つべき処理がないためです。

 そのため、effect_enter_scene関数内のawaitはなくても構いません。今後、他のシーンを作る際に、演出が終わってから何かをしたいこともあるかもしれないのでawaitを付けています。

 それでは次に、このシーン管理関数を、「Title」と「Maze」シーンに組み込んでいきましょう。

次のページ
画面遷移の管理を各シーンで利用しよう

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Godot Engine 2Dゲーム開発入門連載記事一覧

もっと読む

この記事の著者

柳井 政和(ヤナイ マサカズ)

クロノス・クラウン合同会社 代表社員http://crocro.com/オンラインソフトを多数公開。プログラムを書いたり、ゲームを作ったり、記事を執筆したり、マンガを描いたり、小説を書いたりしています。「めもりーくりーなー」でオンラインソフト大賞に入賞。最近は、小説家デビューして小説も書いています(『裏切りのプログラム』他)。面白いことなら何でもOKのさすらいの企画屋です。 

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/21373 2025/07/30 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング