56.

UE5でHighResShotの保存画像のファイル名を取得する方法

編集

Unreal Engine 5(UE5)のHighResShotは撮影後に画像パスを戻り値として返さないため、ファイル名を確実に知る最も実用的な方法は「撮影前に自分でファイル名(パス)を指定して既知の値にしておく」ことです。デフォルトの連番/日時ファイル名のまま後から名前を特定するのは難しいので、保存先と名前をあらかじめ決め打ちし、必要ならOn Screenshot Capturedデリゲートで保存完了のタイミングを受け取る、という流れが基本になります。本記事では、その考え方と具体的な実装パターン、つまずきやすい点を整理します。

この記事の要点
  • HighResShotはファイル名やパスを「取得(戻り値で返す)」する機能を持たない。確実に知りたいなら撮影前に名前を指定するのが基本方針。
  • デフォルトでは プロジェクト/Saved/Screenshots/<プラットフォーム名>/HighResShot_00000.png のような連番で保存される(既存ファイルがあると番号が増えて上書きされにくい)。
  • コンソールコマンドに filename=... を渡せば名前・場所を固定できる。固定名は同名上書きになりやすい点に注意。
  • 保存完了の通知は On Screenshot Captured デリゲート(C++では UGameViewportClient::OnScreenshotCaptured())で受け取れるが、コールバック引数は幅・高さ・ピクセル配列でありパス文字列は含まれない。
  • 保存先ディレクトリは Get Project Saved Dir(C++ FPaths::ProjectSavedDir())等で組み立て、非同期保存プラットフォーム差連番/上書きを踏まえて扱う。

前提:HighResShotはどこに、どんな名前で保存されるか

UE5でコンソールコマンド HighResShot を実行すると、現在のビューを高解像度でキャプチャし、画像ファイルとして書き出します。ファイル名を指定しなかった場合、保存先はプロジェクトの Saved/Screenshots/ 配下で、さらにプラットフォームごとのサブフォルダ(Windowsエディタなら Windows)に分かれるのが標準的な挙動です。例えば次のようなパスになります。

<ProjectDir>/Saved/Screenshots/Windows/HighResShot_00000.png

<ProjectDir>/Saved/Screenshots/Windows/HighResShot_00001.png

ファイル名の末尾は 00000 から始まる連番で、撮影のたびに同じフォルダ内の既存ファイルを避けて番号が増えていくのが基本動作です(バージョンや設定によって命名規則が異なる場合があります)。この「連番が自動で決まる」仕様が、まさに「後からどのファイルが今撮った画像なのか分かりにくい」という問題の原因になります。連番の最大値を毎回スキャンして突き止めることも理論上は可能ですが、複数の保存処理が絡むと取りこぼしやすく、堅牢な方法とは言えません。

基本方針:ファイル名を「取得する」より「先に決める」

HighResShot コマンド自体は、保存したファイルのパスやファイル名を呼び出し側に返しません。したがって考え方としては、次の3つのアプローチに整理できます。優先度の高い順に並べると次のとおりです。

アプローチ概要向いている場面
① 撮影前に名前を指定コマンドに filename=... を渡し、保存先とファイル名を自分で決める。結果としてパスは「最初から既知」。撮ったファイルを確実に後続処理(アップロード・表示等)へ渡したいとき。
② デリゲートで完了を受けるOn Screenshot Captured で保存処理の完了タイミングを受け取り、①で決めたパスとひも付ける。保存が終わってからファイルを開く・読み込むなど、タイミング制御が要るとき。
③ 保存ディレクトリを列挙保存先フォルダ内のファイルを列挙し、最新(最も新しい更新日時)を選ぶ。デフォルト連番のまま運用していて、後追いで特定したいとき(補助的)。

このうち実務でまず採るべきは①です。名前を自分で決めてしまえば「取得」という問題そのものが消えるためです。②は①と組み合わせて「いつ取りに行ってよいか」を知るために使い、③はデフォルト運用を変えられない場合の次善策と位置づけるのが安全です。

① Take High Res Screenshot/コマンドでファイル名を指定する

Blueprintでは Execute Console Command ノードに HighResShot 文字列を渡して実行します。HighResShot は解像度倍率や撮影範囲のほか、ファイル名を指定するパラメータを受け付けます。代表的な書式は次のとおりです(パラメータ構成はバージョンで差があり得ます)。

HighResShot filename="C:/Caps/MyShot_001.png" 3840x2160

// あるいは倍率指定:

HighResShot filename="C:/Caps/MyShot_001.png" 2

ポイントは、filename= に渡したパスがそのまま保存先になるため、コマンドを実行する前の時点で「保存される完全パス」が分かっているということです。つまりBlueprint側で同じ文字列を変数に保持しておけば、それがそのまま「取得したファイル名」になります。撮影ごとに名前が衝突しないよう、変数を組み立てる段階で連番やタイムスタンプ(年月日・時分秒)を自分で付与しておくのが定石です。

// 疑似手順(Blueprint)

FileName = "MyShot_" + 現在日時を"yyyyMMdd_HHmmss"形式で文字列化 + ".png"

FullPath = <保存先ディレクトリ> + FileName

Command = "HighResShot filename=\"" + FullPath + "\" 3840x2160"

Execute Console Command(Command) // ← この時点でFullPathは既知

なお、ファイル名にスペースや日本語、相対パスが混ざると意図したパスに保存されないことがあります。原則として絶対パス・ASCII中心の名前にし、ディレクトリは事前に存在を確認しておくと安定します。デフォルトの日時命名を使いたいだけであれば、bDateTimeAsFilename 系のオプションが利用できる場合もありますが、その場合は「名前が自動で決まる=事前に確定しない」ため、後述の②や③とセットで考える必要があります。

② On Screenshot Captured で保存完了を受け取る

HighResShot による書き出しは即時に完了するとは限らず、内部的には非同期で進みます。「撮った直後にファイルを開こうとしたら、まだ存在しない/書き込み途中だった」という不具合はここに起因します。そこで、保存処理の完了通知を受け取るために On Screenshot Captured デリゲートを使います。

C++では UGameViewportClient::OnScreenshotCaptured() にコールバックをバインドします。コールバックが受け取る引数は 幅(Width)高さ(Height)ピクセル配列(TArray<FColor>)であり、保存先のパス文字列そのものは渡ってこない点に注意してください。つまりこのデリゲートは「いつ・どんなサイズで撮れたか」を知る手段であって、「どこに保存されたか」を教えてくれるものではありません。パスは①で自分が指定した値を保持しておき、デリゲート発火時にそれとひも付けて扱うのが正攻法です。

// C++ イメージ

FString SavedPath = TEXT("C:/Caps/MyShot_001.png"); // 自分で保持

ViewportClient->OnScreenshotCaptured().AddLambda(

  [SavedPath](int32 W, int32 H, const TArray<FColor>& Bitmap){

    // ここで SavedPath が「取得したファイル名」として使える

  });

関連して、C++から能動的に撮影を依頼する場合は FScreenshotRequest::RequestScreenshot(Filename, ...) を使う方法があり、リクエストしたファイル名は FScreenshotRequest::GetFilename() で参照できます。これも結局「自分が渡した名前を引き出す」仕組みであり、コマンドからの自動命名を逆算するものではない点は同じです。Blueprintのみで完結させたい場合は、デリゲート相当のイベントが用意されていないバージョンもあるため、①でパスを固定したうえで、保存完了の判定はファイルの存在確認やわずかな遅延フレームで代替する設計が現実的です。

保存ディレクトリの取得(Project Saved Dir など)

保存先を Saved/ 配下に揃えたい場合は、ハードコードせずにプロジェクトの保存ディレクトリを取得して組み立てます。Blueprintには Get Project Saved Dir 系のノードがあり、C++では FPaths::ProjectSavedDir() が対応します。返るのはプロジェクトの Saved/ までのパスなので、その後ろに Screenshots/ やプラットフォーム名、独自フォルダ名を連結してフルパスを作ります。

// C++ イメージ

FString Dir = FPaths::ProjectSavedDir() / TEXT("Screenshots/MyCaps/");

FString Full = Dir + TEXT("MyShot_001.png");

IFileManager::Get().MakeDirectory(*Dir, true); // 事前にフォルダ作成

デフォルトのままデフォルトフォルダを後追いで列挙したい場合(アプローチ③)は、この保存ディレクトリ内のファイル一覧を取得し、更新日時が最も新しいものを「直近の1枚」とみなします。ただし、複数同時保存やパッケージ製品での書き込み先の違いがあると誤認しやすいため、あくまで補助的手段にとどめ、確実性が必要なら①へ寄せてください。

落とし穴

注意点内容と対策
連番/上書きデフォルトの連番は既存ファイルを避けて増えるが、filename= で固定名を指定すると同名ファイルを上書きしやすい。連番やタイムスタンプを自分で付けて衝突を防ぐ。
非同期保存のタイミングコマンド実行直後はまだ書き込みが終わっていないことがある。撮った直後に開くのではなく、On Screenshot Captured やファイル存在確認、数フレーム待機で完了を待つ。
デリゲートにパスが来ないOn Screenshot Captured の引数は幅・高さ・ピクセル配列のみ。保存パスは自分で保持して関連付ける必要がある。
プラットフォーム差・書き込み先デフォルト保存先のプラットフォーム名サブフォルダや、エディタとパッケージ版での書き込み可能ディレクトリの違いに注意。相対パスや権限の制約も確認する。
パス文字列の扱いスペース・日本語・相対パス混在で意図しない場所に保存されることがある。絶対パスを基本とし、ディレクトリの事前作成と存在確認を行う。

よくある質問(FAQ)

Q1. HighResShotで撮ったファイル名を、コマンドの戻り値として直接取得できますか?
できません。HighResShot はパスやファイル名を呼び出し側へ返さない仕様です。確実に名前を知りたい場合は、コマンドに filename=... を渡してあらかじめ名前を決め、その文字列を自分で保持してください。それが事実上の「取得」になります。

Q2. デフォルトの連番ファイル名のまま、後から「今撮った1枚」を特定したいです。
保存先フォルダ(既定では Saved/Screenshots/<プラットフォーム>/)を列挙し、更新日時が最新のファイルを選ぶ方法があります。ただし非同期保存や複数同時保存があると誤判定しやすいため、可能なら撮影前に名前を指定する方式へ切り替えるのが確実です。

Q3. 撮影直後にファイルを読み込もうとすると、まだ存在しない/途中までしか書けていないことがあります。
保存が非同期で進むためです。On Screenshot Captured デリゲートで完了通知を受けてから読み込む、あるいはファイルの存在確認や数フレームの待機を挟むことで回避できます。

Q4. 各パラメータやデフォルトの命名規則は、自分のバージョンでも同じですか?
保存先や連番の付き方、利用できるオプションはエンジンのバージョンや設定で異なることがあります。重要な挙動は、お使いのUE5バージョンの公式ドキュメントや実機での書き出し結果で確認することをおすすめします。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 床の上に乗ったらイベントを発生させる方法
  2. OverlapAllDynamicとOverlapAllの違い
  3. タイトル画面を作る方法
  4. サードパーソンテンプレートでのキャラクター表示の仕組みと非表示にする方法
  5. ボタンに文字を記載する方法
  6. Event ActorBeginOverlapとOn Component Begin Overlapの違い
  7. キャラクターに特定のオブジェクトとの当たり判定を付ける
  8. 特定のオブジェクトに触れたとき、キャラクターが倒れるようにする
  9. 動いているオブジェクトに静止しているキャラクターが当たり判定を持たない原因と解決方法
  10. 「On Component Hit」に「Cast To ~」で複数のクラスを指定する方法
  11. Blenderファイルをインポートする方法
  12. 鏡を作成する方法
  13. レベルブループリントでキャラクターの出現を設定する方法
  14. サードパーソンテンプレートにおけるキャラクター出現の定義
  15. アイテムに近づいたらボタンを押してイベントを発火させる方法
  16. 画面の中央にメッセージを表示する方法
  17. どこからでも呼び出せるカスタムイベントを作成する方法
  18. カスタムイベントに引数を追加する方法
  19. 「Get Overlapping Actors」から特定のクラスの場合のみ処理を実行する方法
  20. オブジェクトに近づいている間だけメッセージを表示する方法
  21. PCの画面を操作するUIを作る方法
  22. コンテンツブラウザに画像を追加する方法
  23. SetInputMode_UIOnlyを取り消す方法
  24. 特定の画像の上にマウスカーソルを置いたら手マークにする方法
  25. オブジェクトがアウトライナーで選択できない原因と解決策
  26. PlayerStartを作成する方法
  27. メニュー画面を作成して開く方法
  28. 「Esc」キーを押してメニュー画面を開く方法
  29. イベントの「On Clicked」と「On Pressed」の違い
  30. 「Set Input Mode」の種類と使い方
  31. 「Set Game Paused」の使い方と詳細解説
  32. Motion Matchingとは?
  33. 「GameMode」と「GameModeBase」の違い
  34. マップに配置したTargetPointを取得する方法
  35. TargetPointにタグをつけて取得する方法
  36. Spawnしたインスタンスがイベントを実行する方法
  37. 特定の時間ごとに処理を実行する方法
  38. 数値をランダムで出力する方法
  39. ThirdPersonテンプレートでキャラクターの移動を歩くように変更する方法
  40. MaxWalkSpeedを変更する方法
  41. しゃがむ動作を導入する方法
  42. キャラクターのアニメーションを設定する方法
  43. 導入済みのプラグインを確認する方法
  44. Motion Matchingの導入と必要なプラグイン
  45. プレイヤーを非表示にする方法
  46. カメラを傾ける角度を制限させる方法
  47. 配列からランダムに重ならない要素を特定の数取得する方法
  48. カメラの映す画面に文字やエフェクトを付ける方法
  49. キャラクターやメッシュを非表示にした際にカメラが移動しなくなる問題の解決方法
  50. プライマリーデータアセットを活用する方法
  51. プレイヤーのHPといった変数を定義する最適な場所
  52. カメラに映った画面をスクリーンショットとして保存する方法
  53. ゲーム内のカメラ映像を保存して再表示する方法
  54. HighResShot を使って高解像度の画像を保存する方法(UE5)
  55. HighResShotで保存した画像のファイル名を取得する方法
  56. SceneCapture2DとFrameGrabberの画像保存方法の比較
  57. SceneCapture2Dを使用して画像を保存・取得する方法
  58. HighResShotとTake High Res Screenshotの違い
  59. ゲーム終了ボタンを作成する方法
  60. 「Save Game To Slot」の戻り値がfalseになる問題の解決方法
  61. 画面上にメッセージを指定された時間表示させる方法
  62. シェーダコンパイル時間を短縮する方法
  63. 「Take High Res Screenshot」実行時に「シェーダをコンパイル」に長時間待たされる問題とその解決策
  64. データベースを活用する方法
  65. UE5.5がインストールされた環境にUE5.4を追加で導入する方法
  66. World PartitionとWorld Compositionの違い
  67. オープンワールドテンプレートとは?
  68. ポーンをスポーンさせても視点を切り替えない方法
  69. キャラクター同士がすり抜けてしまう問題の解決方法
  70. キャラクターの外見を動的に変更
  71. World Partitionでインスタンスが「アンロード済み」になる問題
  72. データ アセットとデータ テーブルの違い
  73. コンポーネントイベントグラフ内で親クラスの変数にアクセスする方
  74. エディターのソースコードの自動保存の頻度を高める方法
  75. SpawnActorでSpawn Transform Rotationが反映されない理由
  76. ミニマップを表示しポーンの位置を反映する方法
  77. RInterp ToとVInterp Toの違い
  78. 毎秒実行するイベントの定義方法
  79. Niagara のエフェクトにコリジョンを持たせる方法
  80. 「Overlap」と「Hit」の違い
  81. OverlapはあるがHitがない原因
  82. Overlapした位置の座標を取得する方法
  83. ブループリントでレベル間のパラメータを受け渡す方法

最近更新/作成されたページ