【Godot4】exeファイルを実行するランチャーアプリを作った
0. この記事の内容
Godot Engineを用いてexeファイルを登録し、実行するランチャーアプリを作成したので、その紹介と制作時に得た知見などを共有したいと思います。
1. 動機
複数のゲームを展示する機会があり、単に実行ファイルのショートカットを置くだけでは見栄えが悪いため、スクリーンショットや説明文を掲載できるランチャーアプリを作成しました。以前はUnityで開発したランチャーを使用していましたが、古いこともあり使い勝手が悪かったため、最近お気に入りのGodotエンジンを用いて一から作り直すことにしました。
2. 機能
このアプリケーションでは
- ゲームタイトル
- ゲーム制作者
- 説明文
- ロゴ画像
- カバー画像
- スクリーンショット画像
- 実行ファイルのパス
を登録することができます。登録したゲームはゲームタイトル・ロゴ画像・カバー画像と共に一覧に表示され、クリックすることで制作者と説明文が表示されます。
左下の歯車アイコンからEditable
を有効にするとゲームの追加・並べ替え・登録した情報の編集が可能になります。
登録したデータはuser://data.cfg
にConfigFile
を使って保存されています。このアプリの実行ファイルExe Launcher.exe
と同じ階層にdata.cfg
というファイルがある場合はそちらのデータを優先的に読み込みます。
3. 制作に関して
3.1 設計
シンプルなアプリなので、事前に設計などはしていませんが、
- イベント駆動
- 拡張性
- 再利用性
を意識して作成しました。
クラス図
3.2 ハマったこと
3.2.1 GDScriptからexeファイルを実行する
OS.execute(path, args)
でプロセスを実行できますが、この関数を実行するとメインスレッドがブロックされ、アプリケーションがフリーズしてしまいます。この問題を回避するためには、Thread
を用いて別スレッドでプロセスを実行するか、create_process
関数を使って独立したプロセスを生成する必要があります。
今回の実装では、プロセス実行中はアプリケーションを操作不能(ただし、フリーズ状態ではない)とし、プロセスが終了した時点で操作を再開できるようにするため、Thread
を用いて別スレッドでプロセスを実行し、その終了をawaitで待つように実装しました。
thread = Thread.new()
# 別スレッドでプロセスを実行
thread.start(OS.execute.bind(game_info.exe_file_path, []))
# threadが生存中は待機
while thread.is_alive():
await get_tree().process_frame
thread.wait_to_finish()
3.2.2 GDScriptから任意のディレクトリをエクスプローラで開く
このアプリでは、データの保存場所を開く機能を実装しました。先述したcreate_process
からエクスプローラをコマンドから起動すれば良いのですが、単純にOS.create_process("explorer.exe", [path])
としてもパスが正しく認識されず、目的のディレクトリを開くことができませんでした。
様々な試行錯誤の結果、以下のことが判明しました。
- 引数のパス区切りは
/
ではなく\
である必要がある。 - そもそもコマンド実行関連の挙動が怪しい?
最終的に、以下のコードを用いて、任意のディレクトリをエクスプローラで開くことに成功しました。
path = path.replace("/", "\\")
OS.create_process("powershell", ["explorer.exe", path])
4. おわり
Godotは、ゲームエンジンでありながら、Godotエディタ自身がGodotで作られています。そのおかげでUIの関連の機能が豊富で、Unityと比べても使いやすいと感じました。
プロジェクトファイルはMITライセンスで公開しているので、商用利用も含め、自由に活用できます。自身のプロジェクトに組み込んだり、改造して再配布したりすることも可能です。
Discussion
すげーーーーー!かっちょいいですね!!