【Unity】UPM対応時のパスの変更に対応する
はじめに
UPM対応時、パッケージに含めたアセット(Prefab, Texture, etc...)に
アクセスしようとすると開発環境下とPackage内ではパスが異なることに気が付くでしょう。
SerializeFieldなどを利用することができればよいですが、
Editorメニューからアクセスしたいときなどに利用されるstaticメソッド内では利用できません。
今回は自身のソースファイルのパスを開発環境下・Packages内問わず
Unityで利用可能な相対パス
として取得する方法を解説していきます。
前提
先ほど述べさせていただいたUnityで利用可能な相対パス
とは
開発環境下においてはAssets\開発環境下へのパス\...
Packages内においてはPackages\正式なパッケージ名\...
のことを指します。
……が2025/01/14に改めて検証したところどちらも絶対パス指定で良いようです。
再検証の結果上記が間違いであることが判明いたしました。
今回はソースファイルのパスからUnityで利用可能な相対パス
を取得するため
private static string GetSourceFilePath([CallerFilePath]string sourceFilePath = "")
{
return souceFilePath
}
を利用します。
上記を呼び出すと
開発環境下においてはドライブから開発環境下までのパス\Sample.csへのパス
Packages内においては.\Library\PackageCache\正式なパッケージ名@16進数表記の識別番号\Sample.csへのパス
という結果を得ることができます。
実装
前提から行うべき処理を以下のように定義しました。
- パスが
.
から始まるかを条件に分岐する
1がfalseならパスを返却。1がtrueなら次へ
-
.\Library\PackageCache\
をPackages\
に
正式なパッケージ名@16進数表記の識別番号
を正式なパッケージ名
に変換する。 - 変換結果を結合して返却する。
これを基に、コードでは以下のように定義します。
/// <summary>
/// ソースファイルのパスを取得
/// </summary>
/// <param name="sourceFilePath">コンパイル時に解釈</param>
/// <returns>Unityで利用可能な相対パス</returns>
private static string GetSourceFilePathForUnity([System.Runtime.CompilerServices.CallerFilePath] string sourceFilePath = "")
{
if (sourceFilePath[0] != '.') { return sourceFilePath; }
sourceFilePath = sourceFilePath[23..]; // ".\Library\PackageCache\"を削除
string packageName = sourceFilePath.Substring(0, sourceFilePath.IndexOf('@'));
int delimiterIndex = sourceFilePath.IndexOf(@"\"[0]);
sourceFilePath = sourceFilePath.Substring(delimiterIndex, sourceFilePath.Length - delimiterIndex);
return @"Packages\" + packageName + sourceFilePath;
}
このように処理を行うことで開発環境下・Packages内問わず処理を行うことができます。
実際に利用するときはパッケージ直下に上記コードを定義したスクリプトを配置し、
返却値をSystem.IO.Path.GetDirectoryName()
に通すことで
パッケージまでのパスを取得する等の方法が考えられます。
さいごに
ご覧いただき、ありがとうございました。
UPM対応時の一助となれば幸いです。
(2025/01/13)
寒い日が続きますので、お身体にはお気をつけてお過ごしください。
Discussion