デバッグの基本ツール
Unreal Engine (UE) でゲーム開発を進めていると、「なぜか意図した通りに動かない」「エラーは出ていないのに処理が止まっている」という問題に直面します。
効率的にバグの原因を特定するために、UE開発者が最も頻繁に使う基本的なデバッグツールが「Print String 」と「Output Log 」です。本記事では、これら二つのツールの基本的な使い方と応用テクニックを解説します。
Print Stringの基本と応用
「Print String」は、最も手軽で直感的なデバッグ手法です。指定した文字列をゲーム画面の左上、またはOutput Logに出力するノード(Blueprint)または関数(C++)です。
Blueprintでの使い方
Blueprintでは、処理の流れの途中にPrint Stringノードを挿入するだけで、その処理が実行されたことや、その時点での変数の値を確認できます。
実践例:変数の値と処理の実行確認
キャラクターがジャンプした際に、現在の速度と「Jump Executed!」というメッセージを表示する例です。
// Blueprintの実行フロー
Event Jump -> Print String (String: "Jump Executed! Current Velocity: " + Get Velocity)
| パラメータ | 役割 | ベストプラクティス |
|---|---|---|
| In String | 表示したい文字列。変数の値を結合することが多い。 | どの処理からの出力か分かるようにプレフィックスを付ける(例: [Jump])。 |
| Print to Screen | 画面に表示するかどうか。 | 実行中のゲーム内での確認に使います。 |
| Print to Log | Output Logに出力するかどうか。 | 画面表示が邪魔な場合や、永続的なログが必要な場合に使います。 |
| Text Color | 画面表示の色。 | 重要なメッセージは目立つ色(赤など)に設定すると便利です。 |
| Duration | 画面に表示される時間(秒)。 | 複雑な処理を追う際は長めに設定(例: 5.0秒)。 |
| Key | メッセージを識別する一意のキー。 | 同じキーを持つメッセージは新しいもので上書きされます。連続する値の確認に非常に有効です。 |
Keyを使った値の追跡
Keyパラメータは、Print Stringをデバッグツールとして強力にする機能です。同じKeyを設定すると、画面上のメッセージが常に最新の値に更新されます。
例えば、TickイベントでキャラクターのHPを毎フレーム表示したい場合、Keyに固定の値を設定することで、画面左上にHPがリアルタイムで更新され続けるようになります。これにより、画面がメッセージで埋め尽くされるのを防ぎつつ、特定の変数の変化を追跡できます。
Output Logの活用
Print Stringが「手軽な目視確認」だとすれば、「Output Log」はUEのシステム全体から発せられる情報を集約するデバッグの心臓部 です。BlueprintやC++からのメッセージだけでなく、エンジンの警告、エラー、ロード情報など、あらゆる情報がここに記録されます。
Output Logの開き方と基本操作
Output Logは、エディタ上部のウィンドウ > デベロッパーツール > Output Log から開けます。
- フィルタリング: ログウィンドウ上部の検索バーで、特定のキーワード(例:
Error,Warning,MyDebug)を含むメッセージのみを表示できます。 - ログカテゴリ: UEのログは
LogTemp,LogBlueprint,LogAIなどのカテゴリに分類されています。フィルタリングと組み合わせて、必要な情報だけを抽出できます。
C++でのログ出力:UE_LOGマクロ
C++でデバッグ情報をOutput Logに出力する際は、UE_LOGマクロを使用します。これはC++開発における最も標準的なデバッグ手法です。
// ログカテゴリを定義(通常はプロジェクト名などを使用)
DEFINE_LOG_CATEGORY_STATIC(LogMyGame, Log, All);
// 警告メッセージを出力する例
UE_LOG(LogMyGame, Warning, TEXT("プレイヤー %s がダメージを受けました。残りHP: %f"), *GetPlayerName(), CurrentHealth);
// エラーメッセージを出力する例
if (TargetActor == nullptr)
{
UE_LOG(LogMyGame, Error, TEXT("ターゲットアクターがNullです!処理を中断します。"));
return;
}
UE_LOGの第二引数(Warning, Error, Logなど)はログの重要度(Verbosity) を示します。
| Verbosity | 役割 | 用途 |
|---|---|---|
| Error | 致命的な問題。ゲームの続行が困難な場合。 | 必須リソースのロード失敗、Nullポインタ参照など。 |
| Warning | 潜在的な問題。すぐに修正すべき非致命的なエラー。 | 非推奨関数の使用、予期せぬ入力値など。 |
| Log | 標準的な情報メッセージ。 | 処理の開始/終了、変数の値の確認など。 |
| Display | ユーザーに表示すべき重要な情報。 | デバッグ情報として画面にも表示したい場合。 |
BlueprintからOutput Logへの出力
BlueprintのPrint Stringノードは、デフォルトでOutput Logにも出力されます(Print to Logがチェックされている場合)。しかし、より詳細なログカテゴリを指定したい場合は、Print Stringではなく、C++でカスタムのログ出力関数を作成し、それをBlueprintから呼び出すのが一般的です。
ベストプラクティスとよくある間違い
ベストプラクティス
| プラクティス | 詳細 | 効果 |
|---|---|---|
| ログにコンテキストを含める | Print StringやUE_LOGのメッセージに、どのクラス、どの関数、どの変数の値かを含める(例: [MyActor::Tick] Current HP: 100)。 | ログが大量に出ても、どの処理からの出力か一目で判別できる。 |
| ログの重要度を使い分ける | UE_LOGでは、単なる情報にはLog、問題の兆候にはWarning、致命的な問題にはErrorを使い分ける。 | Output Logのフィルタリング機能が最大限に活かされ、問題の緊急度に応じて対応できる。 |
| Print StringのKeyを活用する | TickやUpdateなど、頻繁に実行される処理で変数を追跡する際は、必ずKeyを設定して画面をクリーンに保つ。 | 画面がデバッグメッセージで埋め尽くされるのを防ぎ、リアルタイムな値の確認が可能になる。 |
| デバッグ用ブール変数を用意する | 複雑なデバッグログを有効/無効にするためのbDebugModeのようなブール変数をクラスに用意し、ログ出力の前にチェックする。 | デバッグが完了したら、変数一つで全てのログ出力を無効化でき、リリースビルドでのパフォーマンス低下を防げる。 |
よくある間違い
-
Print StringのDurationを無視する:
- 間違い:
Durationをデ フォルトの2.0秒のままにして、一瞬で消えてしまうメッセージを追おうとする。 - 解決策: 追跡したい処理に応じて
Durationを5.0秒や10.0秒に設定するか、Keyを使ってメッセージを永続化させる。
- 間違い:
-
Output Logをチェックしない:
- 間違い: 画面に表示される
Print Stringの結果だけに頼り、Output Logに記録されているWarningやErrorを見逃す。 - 解決策: 処理が意図通りに動かない場合、まずOutput Logの
ErrorとWarningフィルタをチェックする習慣をつける。
- 間違い: 画面に表示される
-
C++で
printfやstd::coutを使う:- 間違い: C++の標準的な出力関数をデバッグに使用する。
- 解決策: UEのフレームワークと統合されている
UE_LOGマクロを常に使用する。これにより、ログの重要度設定、フィルタリング、ファイルへの出力など、UEのログシステムの恩恵を受けられる。
Print StringとOutput Logの使い分け
Print StringとOutput Logは、Unreal Engine開発における最も基本的なデバッグツールですが、その活用方法を理解することで、バグ修正にかかる時間を劇的に短縮できます。
| ツール | 主な用途 | 特徴 |
|---|---|---|
| Print String | 処理の実行確認、変数のリアルタイムな画面表示。 | 手軽、直感的。Keyによる値の永続化が強力。 |
| Output Log | システム全体のエラー/警告の監視、C++からの詳細なログ出力。 | 永続的、フィルタリング可能。システムの深層を把握できる。 |
デバッグは開発プロセスの一部であり、これらのツールを使いこなすことは、プロのエンジニアへの第一歩です。常に「この処理は本当に実行されたか?」「この変数の値は今どうなっているか?」という疑問を持ち、Print StringとOutput Logを使ってそれを検証する習慣をつけましょう。