UnityのDebugクラスを使って、QAとデバッグのプロセスを改善する方法を学びましょう。
についてはすでにご存知かもしれませんが 関数関数はすでによく知られているかもしれませんが、Unity Debug クラスはテストとデバッグを高速化するのに役立つ他の多くの便利な関数をサポートしています。このページでは、シーンビューやゲームビューでギズモを可視化するためのDebugクラスの使い方や、スクリプトからエディタでプレイモードを一時停止する方法などを説明します。
Unityを使い慣れた人なら、エディターが生成したエラーや警告、その他のメッセージを表示するためにコンソールウィンドウを使ったことがあるでしょう。また、Debugクラスを使ってコンソールに自分のメッセージを表示したこともあるだろう。
しかし、Debug.Log Messageだけに限定されるわけではない。コンソール・ウィンドウに文字列を出力する場合、3つのタイプ(エラー、警告、メッセージ)のいずれかを指定することができ、それぞれにアイコンのタイプがあります。
3つのバリエーションがある:
- Debug.Log ("これはログメッセージです。")
- Debug.LogWarning ("これは警告メッセージです。")
- Debug.LogError ("これはエラーメッセージです。")
コンソール・ウィンドウを使って、好みに応じてメッセージをフィルタリングすることができます。また、コンソールウィンドウでエラーポーズを有効にすることで、Debugクラスを経由してコンソールに書き込んだエラーがUnityのプレイモードを一時停止させることができます。
Unityやあなた自身のメッセージによってConsoleウィンドウに出力されたものは、すべてログファイルに追加されます。各オペレーティング・システムによってログ・ファイルの保存場所は異なるので、各システムの仕様をドキュメントで確認してください。
エラーや例外がスローされると、コンソールウィンドウにエラーメッセージとともにスタックトレースが表示され、エラーの発生原因や発生場所を理解するのに役立ちます。Debug.Logではコンソールにメッセージを送信することができますが、スタックトレースに表示される詳細レベルを設定することもできます。
デフォルトでは、コンソールの出力はメッセージを生成したコード行にリンクしており、エントリーが表示される原因となった行、メソッド、または関数呼び出しのシーケンスを簡単に特定できます。
選択したIDEでスクリプトが開かない場合は、ファイル > 環境設定 > 外部ツールに 移動し、ドロップダウンから「外部スクリプトエディタ」を選択します。
スタック・トレースに表示される情報は、エディタのFile > Build Settings... > Player Settings ... > Other Settingsで設定できます。
各ログタイプで利用可能なオプションは以下の通りです:
- いない:スタックトレースはログに出力されない。
- ScriptOnly:管理されたスタックトレースのみが出力される。設定を変更していない場合は、これがデフォルトのオプションです。
- フルだ:ネイティブとマネージドのスタックトレースが記録される。
ログが混雑してきたら、コンソールの検索機能を活用しよう。検索語を入力すると、コンソールはメッセージをフィルタリングし、一致するテキストを含むメッセージのみを表示します。
コンソール]メニューボタンをクリックし、メニューから[ログエントリ]>[X]行を選択し、[X]は各エントリの表示行数です。
文字列.書式 C#のString.Formatメソッドを使用すると、フォーマットされた変数データを埋め込んだ文字列を作成できます。Debugクラスは Debug.LogFormatがあります。
最初のパラメーターはフォーマットされたメッセージ文字列である。中括弧でインデックス値を囲むと、パラメータindex-1が存在する場合、そのToStringメソッド、またはSystem文字列変換を使用して、パラメータindex-1に置き換えられます。上記のコード例では、14行目の{0}はorigin.ToString()に置き換えられます。
もっと複雑な例はこうだ:
Debug.LogFormat("At Start transform.position={0}, transform.rotation=}", transform.position, transform.rotation);
{0}はパラメータ1のtransform.positionに、˶はパラメータ2のtransform.rotationに置き換えられる。いずれの場合も、Vector3とQuaternionプロパティのToStringメソッドが使用されます。結果はこのようになる:
「原点は (0.00, 0.00, 0.00)
UnityEngine.Debug:LogFormat (string,object[])”
また、これらのログメソッドにオプションの第2パラメータを与えることで、そのメッセージが特定のGameObjectに関連したものであることを示すことができます:
Debug.LogWarning("I come in peace!", this.gameObject);
フォーマットされた変数データを表示する場合、Debug.LogFormatには警告バージョンとエラーバージョンがあります:
- Debug.LogWarningFormat("The value of Cube.position.x is {0:0.00}", transform.position.x)
- Debug.LogErrorFormat("The value of Cube.position.x is {0:0.00}", transform.position.x)
Debug.Logformatを使用してコンソールに浮動小数点値を送信すると、デフォルトでは小数点以下の6桁の数字が表示されます。この動作は、カスタム数値フォーマット文字列で制御できる。
Debug.LogFormat("pi = {0:0.00}", Mathf.PI);
コロンを使うと、フォーマット文字列0.00は、値の整数部分、小数部の区切り文字、区切り文字に続く2つの数字を表示します。最後の数字は、お馴染みの方法で次の値を基準に四捨五入される。
この例では、出力は次のようになる:π = 3.14
Debug.Assert()は、Debug.Log()メソッドに似ていますが、コンソールにメッセージを記録する代わりに、条件をテストし、その条件が偽の場合にエラー・メッセージを表示します。これは、開発中に仮定を検証し、エラーを発見するために使用される。
アサーションは、プログラムが予期せぬ状態に陥らないことをチェックする素晴らしい方法だ。if文の中にLogを埋め込むようなものだ。クラスのプロパティの代入に依存するメソッドで作業している場合、アサーションはエラーの追跡に役立ちます。
Debug.Assert()が呼び出されると、テストする条件と、その条件が偽の場合に表示するオプションのメッセージという2つのパラメータを受け取ります。条件が真であれば、何も起こらず、プログラムは実行され続ける。条件が偽の場合、プログラムの実行は停止し、エラーメッセージがエディターに表示されます。
void SetColor(カラー)
{
Debug.Assert(material != null, "ChangeColor: material not assigned");
material.SetColor("_Color", color);
}
SetColor を呼び出したときにマテリアルが割り当てられていない場合、コンソールに「SetColor: Material not assigned」と表示されます。
Debug.Break()はUnityのDebugクラスが提供するメソッドで、ゲームの実行を一時停止し、コードの現在のポイントでデバッガに入るために使用します。ゲームの状態を検査し、コードを一行ずつ調べてバグを見つけ、修正することができる。
Debug.Break()が呼び出されると、ゲームの実行が停止され、デバッガーウィンドウが開きます。これにより、ゲームの状態を調べ、必要に応じてコードをデバッグすることができる。デバッガを使用して、コードをステップ実行したり、ブレークポイントを設定したり、メモリ内の変数やオブジェクトを検査したりできます。
例えば、NPCがプレイヤーキャラクターからターゲット距離内に入ったときにゲームを止めたいとします。ゲームが中断すると、インスペクタでその状態を調べることができます:
float dist = Vector3.Distance(transform.position, npc.position);
if ( dist < 5) Debug.Break();
Debug.DrawLineとDebug.DrawRayはUnityのDebugクラスが提供する2つのメソッドで、ビジュアルデバッグに使用されます。衝突やレイキャストなど、物理関連のコードをテストしたり視覚化したりするのに便利だ。どちらも、GameビューとSceneビューの両方で見えるように、色のついた線を引くことができます。例えば、Debug.DrawRayを使用して弾丸の軌跡やレーザービームの経路を視覚化し、Debug.DrawLineを使用してコライダの境界線やオブジェクトの動きを視覚化することができます。
Debug.DrawLineは、シーン内の2点間に直線を引くために使用します:
Debug.DrawLine(transform.position,target.position,Color.white,0,false);
始点、終点、そしてオプションの色である。例えば、次のコードは始点と終点の間に白線を引く:
public static void DrawLine(Vector3start,Vector3end,Colorcolor = Color.white, float duration = 0.0f, bool depthTest = true);
パラメータ
- スタート線が始まるべきワールド空間の点
- 終了:線の終点となるワールド空間の点
- 色だ:線の色
- 期間である:行を表示する時間(秒)。0 は単一フレームのラインを表示
- 深さテスト:線が前景オブジェクトに隠れるようにする
コード例では、Skeleton GameObjectにアタッチされたMonoBehaviourスクリプトのUpdateメソッドを実行すると、上のような画像になります。ラインは、ギズモが有効になっている場合のみ、ゲームビューに表示される。ゲームビューペインの右上にあるギズモボタンをクリックして、ギズモを有効にします。ラインはシーンビューでも見える。
DrawLineの代替はDrawRayである。Debug.DrawRayは、指定された原点から始まり、指定された方向に伸びるレイをシーンに描画するために使用されます。デフォルトでは無限の光線だ。Debug.DrawRay()で描画されたレイがコライダーにぶつかると、交点で止まり、それ以上先には進みません。この動作はUnityのレイキャストと同じで、シーン内のオブジェクト間の衝突を検出するために使用されます。
ここで、2番目のパラメータは、線の方向と長さを定義する。線は始点から 始点+dirまで引かれる:
public static void DrawRay(Vector3start,Vector3dir,Colorcolor = Color.white, float duration = 0.0f, bool depthTest = true);
コード例のパラメーターは以下の通り:
- スタート線が始まるべきワールド空間の点
- 監督世界空間における線の方向と長さ
- 色だ:線の色
- 期間である:行を表示する時間(秒)。
- 深さテスト:線が前景オブジェクトに隠れるようにする
別のコード例だ:
Vector3 dir = transform.TransformDirection(Vector3.forward) * 3;Debug.DrawRay(transform.position,dir,Color.white,0,false);
このコード例では、Skeleton GameObjectにアタッチされたMonoBehaviourスクリプトのUpdateメソッドが、上の画像になります。長さのあるレイは、近接テストのデバッグに便利です。ここで、レイの長さは3ワールド単位である。もし攻撃が3ユニットから開始されるのであれば、あなたのシーンで3ユニットがどれくらいの長さなのかを視覚的にテストすることができる。
ギズモはUnityのビジュアルデバッグのための強力なツールです。Sceneビューで簡単な2Dや3Dの図形、線、テキストを描くことができ、ゲームの世界で起こっていることを簡単に見て理解することができます。
わずか数行のコードで、Sceneビューに簡単な図形や線を描くことができる。そのため、ゲームメカニクスのプロトタイプを素早く作成し、テストするための理想的なツールとなります。リアルタイムで描画されるため、コード変更の結果を即座に確認し、必要な変更を加えることができる。
ギズモは、コードだけでは理解しにくい複雑なゲームの仕組みを視覚的に示している。例えば、上の画像のように、ギズモを使って弾道を示す線を引いたり、トリガーゾーンの境界線を視覚化することができる。
ギズモを使って、他のチームメンバーがあなたのコードやゲームの仕組みを理解しやすくなるような視覚的な補助を作りましょう。
ギズモはパフォーマンスにほとんど影響を与えないので、パフォーマンスを落とすことなく自由に使うことができる。
ギズモアイコンは、シーンビューとゲームビューの右上にあります。カスタムギズモを追加するには、OnDrawGizmosコールバックを含むスクリプトを追加する必要があります。このスクリプトは、GameObjectの位置から3ワールドユニット前方にワイヤーフレームの立方体を描く。立方体の大きさは、Vector3型のクラス・プロパティvsizeで定義されます: public Vector3 vsize = new Vector3(1f, 1f, 1f);
void OnDrawGizmos()
{
// トランスフォームの位置に黄色の球を描く。
Gizmos.color = Color.yellow;
Vector3 position = transform.position + transform.TransformDirection(Vector3.forward) * 3;
Gizmos.DrawWireCube(position, vsize);
}
ギズモのドロップダウンをクリックして可視性をコントロールする。OnDrawGizmosコールバックを持つすべてのスクリプトがリストされます。
Gizmoクラスを使ったその他の便利なメソッドについては、ドキュメントを参照してください。
例外のスローは、プログラムの実行中にエラーや例外的な状況が発生したことを示すためにプログラミングで使われるテクニックである。この方法を使ってスレッドの実行を止めることで、それ以上のダメージを防ぐことができる。
Unityでは、例外のスローは他のプログラミング言語と同じように使用されます。
例外がスローされ、コード内でキャッチされ処理されなかった場合、プログラムの実行は通常停止し、アプリから放り出されてオペレーティング・システムに戻ることになる。Unityでは、プログラムの実行は即座に停止され、実行環境は例外を処理できる "catch "ブロックを探す。キャッチ・ブロックが見つからない場合、プログラムは終了し、例外はコンソールに記録されます。
例外を投げることで、エラー処理ロジックを他のプログラム・ロジックから切り離すことができ、よりクリーンなコードを書くことができるからだ。例外を投げることで、エラーを伝えるために戻り値やグローバル・ステートに依存することなく、呼び出し側に何か問題が起きたことを知らせることができる。
Unityで例外を投げるには、throwキーワードの後に例外オブジェクトを続けます。例を挙げよう:
if (target == null)
{
throw new System.NullReferenceException("target not set!");
}
エディタでコードを実行すると、Unityやアプリがクラッシュする代わりに、スローされたエラーをキャッチしてDebug.LogError()を実行します。
Unityで例外を使用すると、エラーを早期にキャッチできます。また、エラーが発生した場所やその原因についてより多くの情報を提供することで、デバッグを容易にすることもできる。
Unityプロジェクトのテスト、デバッグ、パフォーマンスの向上については、これらの記事で詳しく説明しています:
- Roslynアナライザでゲームコードをデバッグする方法
- Unity Test Frameworkでゲームの自動テストを実行する方法
- Microsoft Visual Studio Codeでデバッグワークフローをスピードアップ
- Microsoft Visual Studio 2022でコードをデバッグする方法
- Unityプロジェクトのテストと品質保証のヒント
Unity開発者のための高度なベストプラクティスとインストラクションを、これらの電子書籍でご覧ください:
Unityのベストプラクティスハブでは、さらに多くの高度なリソースを見つけることができます。