(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

(:3[kanのメモ帳]



呼び出し元のファイルのパス、メソッド名、行数を取得する属性CallerFilePath、CallerMemberName、CallerLineNumber【C#】【属性】【Unity】


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



この記事でのバージョン
Unity 2018.4.13f1


はじめに

以前「移動する可能性のある任意のアセットやディレクトリ(フォルダ)のパスを取得する方法

という記事を投稿した際に



CallerFilePathというものの存在を知りました。



ということで今回は、CallerFilePathを使ってみようという感じの記事です!


CallerFilePath

そもそもCallerFilePathとはなんぞやという話からですが、

C#(というか.NET)の属性で、ドキュメントには以下のようにあります。

呼び出し元を格納するソースファイルの完全パスを取得できるようにします。 これは、コンパイル時のファイルパスです。


つまりCallerFilePathとはメソッドを呼び出し元のファイルのパスを得るためのものです。

ちなみにCallerMemberNameで呼び出し元のメソッド名

CallerLineNumberで呼び出し元の行数を取得する事も可能です。


実際に使う際は以下のような感じでメソッドの引数に属性を付与します。

/// <summary>
/// 呼び出し元の情報をログで表示する
/// </summary>
public static void ShowTraceLog(
  [CallerMemberName] string memberName       = "", //呼び出し元のメソッド名
  [CallerFilePath]   string sourceFilePath   = "", //呼び出し元のファイルのパス
  [CallerLineNumber] int    sourceLineNumber = 0   //呼び出し元の行数
  ){
  Debug.Log("呼び出し元のメソッド名 : "    + memberName);
  Debug.Log("呼び出し元のファイルのパス : " + sourceFilePath);
  Debug.Log("呼び出し元の行数 : "         + sourceLineNumber);
}


例えばこれをAssets直下にあるNewBehaviourScript.csから実行すると、

using UnityEngine;
using System.Runtime.CompilerServices;//Caller系の属性を使うのに必要

public class NewBehaviourScript : MonoBehaviour {
  private void Start(){
    ShowTraceLog(); 
  }

  /// <summary>
  /// 呼び出し元の情報をログで表示する
  /// </summary>
  public static void ShowTraceLog(
    [CallerMemberName] string memberName       = "", //呼び出し元のメソッド名
    [CallerFilePath]   string sourceFilePath   = "", //呼び出し元のファイルのパス
    [CallerLineNumber] int    sourceLineNumber = 0   //呼び出し元の行数
    ){
    Debug.Log("呼び出し元のメソッド名 : "    + memberName);
    Debug.Log("呼び出し元のファイルのパス : " + sourceFilePath);
    Debug.Log("呼び出し元の行数 : "         + sourceLineNumber);
  }
  
}
f:id:kan_kikuchi:20191220061820j:plain


NewBehaviourScript.csへのパスや呼び出したメソッドであるStart、

さらに呼び出し元の行数も取得出来ている事が分かります。


もちろん、別のスクリプトから実行する事も可能です。

using UnityEngine;

public class Sample : MonoBehaviour {
    
  private void Awake() {
    NewBehaviourScript.ShowTraceLog();
  }
  
}
f:id:kan_kikuchi:20191220061549j:plain


ちなみに、Assets以下のパスが欲しい場合

AssetsまでのパスであるApplication.dataPathを使って相対パスを取得するのが良さそうです。

using UnityEngine;
using System;//Uriを使うのに必要
using System.Runtime.CompilerServices;//Caller系の属性を使うのに必要
/// <summary>
/// 呼び出し元の情報をログで表示する
/// </summary>
public static void ShowTraceLog([CallerFilePath]string sourceFilePath = ""){
  //呼び出し元のパス
  Debug.Log("sourceFilePath : " + sourceFilePath);

  //Assetsまでのパス
  Debug.Log("dataPath : " + Application.dataPath);
    
  //呼び出し元のパスをAssetsからのパスに変換
  string relativePath = (new Uri(Application.dataPath)).MakeRelativeUri(new Uri(sourceFilePath)).ToString();
  Debug.Log("relativePath : " + relativePath);
}
f:id:kan_kikuchi:20191220061736j:plain


ただし、CallerFilePathは呼び出し元のパスを取得するので、

スクリプト自身がどこにいるのかを知りたい場合は、

以下のように自分自身のパスを教えてくれるメソッドを作る必要があります。

using System;//Uriを使うのに必要
using System.Runtime.CompilerServices;//Caller系の属性を使うのに必要
/// <summary>
/// 呼び出し元のパスを取得
/// </summary>
public static string GetSelfPath([CallerFilePath]string sourceFilePath = ""){
  return sourceFilePath;
}
    
/// <summary>
/// 呼び出し元のパス(Assetsから)を取得
/// </summary>
public static string GetSelfPathFromAssets([CallerFilePath]string sourceFilePath = ""){
  return (new Uri(Application.dataPath)).MakeRelativeUri(new Uri(sourceFilePath)).ToString();
}


例えばこれをAssets直下にあるNewBehaviourScript.csから実行すると、以下の通りです。

Debug.Log("SelfPath : "           + GetSelfPath());
Debug.Log("SelfPathFromAssets : " + GetSelfPathFromAssets());
f:id:kan_kikuchi:20191220064937j:plain



------------追記------------

ここら辺のパス周りをいい感じに扱えるクラスを作りました!



------------追記おわり------------