(:3[kanのメモ帳]

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

(:3[kanのメモ帳]



移動する可能性のある任意のアセットやディレクトリ(フォルダ)のパスを取得する方法【Unity】【エディタ拡張】


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



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

はじめに

前回Unityで使えるAudioManagerというものを公開したのですが、



この実装の際にBGMやSEなどのディレクトリへのパスを知りたいという状況がありました。

f:id:kan_kikuchi:20191213195832j:plain


普通ならAssets/AudioManager_KanKikuchi/Resources/BGMのように指定すればいいのですが、

そうすると、トップのAudioManager_KanKikuchiという

ディレクトリが移動したり、名前を変更した場合に対応できなくなってしまいます。

f:id:kan_kikuchi:20191213195857j:plain


自分のプロジェクトの場合はこんな事を考える必要はないのですが、

上記の記事やアセットストアのように公開する事が目的の場合、

トップのディレクトリが移動出来ないというのはかなり不便です。


という事で今回は、

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


ディレクトリを検索する方法

まずAudioManager_KanKikuchiというディレクトリの名前を変更しない前提なら、

単純にそのディレクトリ名で検索し、そこからBGMへのパスを作成するという方法が使えます。

f:id:kan_kikuchi:20191213201113j:plain


具体的には以下のようなコードになります。

using System.IO;
using System.Linq;
using UnityEngine;
//AudioManager_KanKikuchiディレクトリへのパスを取得
var topDirectoryPath = Directory
  .GetDirectories("Assets", "*", System.IO.SearchOption.AllDirectories) //Assets以下の全ディレクトリのパスを取得
  .FirstOrDefault(path => System.IO.Path.GetFileName(path) == "AudioManager_KanKikuchi"); //その中からディレクトリ名がAudioManager_KanKikuchiのものを取得

//BGMまでのパスを生成、ログで表示
var bgmPath = topDirectoryPath + "/Resources/BGM";
Debug.Log(bgmPath);


これなら例えば、Testというディレクトリの下に配置されても問題なくパスが取得可能です。

f:id:kan_kikuchi:20191213200718j:plain


なお、BGMというディレクトリを検索すれば一発でパスが分かりますが、

BGMは同名のディレクトリが作られる可能性が結構高そうなので避けています。


もちろんAudioManager_KanKikuchiという同名のディレクトリがある場合も問題ありですが、

それはないだろうという前提にもなっています。


スクリプトを検索する方法

次にAudioManager_KanKikuchiというディレクトリの名前が変更されても良いという前提の場合は、

そのディレクトリ内にある、名前が変更されなさそうでかつ、被らなそうなスクリプトを検索し、

そこから上部のディレクトリ(デフォルトならAudioManager_KanKikuchi)へのパスを作成し、

さらにBGMへのパスを作成するという方法が使えます。

f:id:kan_kikuchi:20191213201157j:plain


具体的には以下のようなコードになります。

using System.IO;
using System.Linq;
using UnityEngine;
//スクリプトがある所へのパス取得
string scriptPath = Directory
  .GetFiles("Assets", "*", System.IO.SearchOption.AllDirectories)
  .FirstOrDefault(path => System.IO.Path.GetFileName(path) == "AudioManagerSettingEditor.cs");
        
//パスの中からEditorディレクトリのインデックスを取得
var editorIndex = scriptPath.IndexOf("Editor");
    
//上部のディレクトリへのパスを取得(ついでにWindowsで問題が起きないように区切りを変換)
var topDirectoryPath = scriptPath.Substring(0, editorIndex).Replace("\\", "/");
    
//BGMまでのパスを生成、ログで表示
var bgmPath = topDirectoryPath + "Resources/BGM";
Debug.Log(bgmPath);


これなら例えば、New Flolderというディレクトリの下に

AMと名前を変更されて配置されても問題なくパスが取得可能です。

f:id:kan_kikuchi:20191213202033j:plain



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

CallerFilePathGUIDを使う方法もありました!

f:id:kan_kikuchi:20191223093929j:plain



f:id:kan_kikuchi:20200113091107j:plain


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


おわりに

こんな感じで何か目印さえあれば、わりと簡単に移動する可能性のパスを取得する可能です。

他にもっと良い方法がある気もしますが、

外部で使ってもらう事前提のコードを書く際には参考にしてみてください。


余談ですが、単純にアセットのパスを取得したい場合は

AssetDatabase.GetAssetPathが使えます。

var audioClip = Resources.Load<AudioClip>("BGM/fantasy14");
Debug.Log(AssetDatabase.GetAssetPath(audioClip));
f:id:kan_kikuchi:20191213202309j:plain