以下のようなフォルダ構成になっている時に
[hanako]や[tarou]というフォルダ一覧を取得したいのですが、
■フォルダ構成 Asset - Resources - images - characters - hanako - - hanako_smile.png - hanako_sad.png - tarou - - tarou_smile.png - tarou_sad.png
以下のようにResources.LoadAllを使うとpngのファイル名のObject.nameで取得してしまいます。
[hanako]や[tarou]というフォルダ名の方を取得したいのですが方法はあるでしょうか?
c#
1UnityEngine.Object[] characters = Resources.LoadAll("images/characters");
◆環境
Unity2020.3.11f1
Windows10
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答2件
1
ベストアンサー
これはどうやらややこしそうですね。ちょっと調べた限りではリソースのパス文字列を取得する方法は見当たりませんでした...
非公開のメソッドにResourcesAPIInternal.GetAllPathsなんてものが見つかったのですが、どうやらこれもビルド後にはこのメソッド自体が消えてしまうようでした。
アニメーションステート名だとかの場合も似たような感じですが、想像しますにおそらく最終的なプログラムの中にこういった文字列そのもののデータは存在せず、文字列から計算されたハッシュ値みたいなものだけが残っているんじゃないかと思います。ですのでリソースパスを与えてやれば、その文字列からハッシュ値を計算して適切なリソースを持ってくることができるものの、逆にリソースのハッシュ値からリソースパスを復元することはできず、あんな風に一方向的な仕様になっているのかもしれません。
どうやらbboydaisukeさんのおっしゃるように「c# - Get file names from Resources sub folder - Stack Overflow」に寄せられたProgrammerさんのご回答のようなことをする必要がありそうです。あれをアレンジして下記のようなスクリプトを作ってみましたが、いかがでしょうか?
ResourcePaths.cs
C#
1using System; 2using System.Linq; 3using UnityEngine; 4#if UNITY_EDITOR 5using System.IO; 6using UnityEditor; 7using UnityEditor.Build; 8using UnityEditor.Build.Reporting; 9#endif 10 11public class ResourcePaths : ScriptableObject 12{ 13 public string[] paths; 14} 15 16public static class ResourcePathUtility 17{ 18 private static Func<string, string[]> getAllPaths; 19 private static ResourcePaths resourcePaths; 20 21 private static ResourcePaths Paths => resourcePaths ??= Resources.Load<ResourcePaths>("ResourcePaths"); 22 23 /// <summary> 24 /// <paramref name="parentPath"/>の階層下にあるすべてのリソースのリソースパスを取得します。 25 /// </summary> 26 /// <remarks> 27 /// <paramref name="parentPath"/>は大文字と小文字を区別しません。 28 /// 戻り値は小文字で表されます。 29 /// </remarks> 30 /// <param name="parentPath">親階層のパス。</param> 31 /// <returns>リソースパス文字列の配列。</returns> 32 public static string[] GetResourcePaths(string parentPath) 33 { 34 #if UNITY_EDITOR 35 // エディター上で実行したときには、GetAllPathsで得たパスを加工して出力する 36 // GetAllPathsで得られるのはAssetsで始まるファイルシステム上のパスのようなので、それを 37 // Resourcesを起点とするようにし、また大文字小文字を区別せず、拡張子を含めないように加工する 38 // なお、フォルダ名の中のドットは拡張子とは見なされず、またファイル名の中に複数のドットがある場合は 39 // 末尾の部分が拡張子と見なされるらしい? 40 getAllPaths ??= (Func<string, string[]>)Delegate.CreateDelegate( 41 typeof(Func<string, string[]>), 42 null, 43 typeof(Resources).Assembly.GetType("UnityEngine.ResourcesAPIInternal").GetMethod("GetAllPaths")); 44 parentPath ??= string.Empty; 45 const string resourceFolderName = "/resources/"; 46 return getAllPaths(parentPath).Select( 47 path => 48 { 49 var lowerPath = path.ToLowerInvariant(); 50 return lowerPath[(lowerPath.IndexOf(resourceFolderName, StringComparison.Ordinal) + resourceFolderName.Length)..lowerPath.LastIndexOf('.')]; 51 }) 52 .ToArray(); 53 #else 54 // ビルド後に実行した場合は、保存しておいたResourcePathsからパスを得て出力する 55 parentPath = parentPath.ToLowerInvariant(); 56 return Paths.paths.Where(path => path.StartsWith(parentPath)).ToArray(); 57 #endif 58 } 59 60 /// <summary> 61 /// <paramref name="parentPath"/>の子項目の名前を取得します。 62 /// </summary> 63 /// <remarks> 64 /// <paramref name="parentPath"/>は大文字と小文字を区別しません。 65 /// 戻り値は小文字で表されます。 66 /// </remarks> 67 /// <param name="parentPath">親階層のパス。</param> 68 /// <returns>子項目名の配列。</returns> 69 public static string[] GetChildNames(string parentPath) 70 { 71 parentPath ??= string.Empty; 72 parentPath = parentPath.ToLowerInvariant(); 73 74 // まずparentPath以下のすべてのリソースパスを取得し、それら文字列の頭からparentPathを削除、 75 // さらにスラッシュで分割して最初の要素をとってくる 76 return GetResourcePaths(parentPath) 77 .Select(path => path[(path.IndexOf(parentPath) + parentPath.Length)..] 78 .Split('/', StringSplitOptions.RemoveEmptyEntries) 79 .FirstOrDefault()) 80 .Where(path => path != null) 81 .Distinct() 82 .ToArray(); 83 } 84} 85 86#if UNITY_EDITOR 87internal class ResourcePathRecorder : IPreprocessBuildWithReport 88{ 89 public int callbackOrder => 0; 90 91 // ビルド時にAssets/Resources/ResourcePaths.assetにリソースパスの一覧を保存しておく 92 public void OnPreprocessBuild(BuildReport report) 93 { 94 var paths = ScriptableObject.CreateInstance<ResourcePaths>(); 95 const string resourceFolderPath = "Assets/Resources"; 96 if (!Directory.Exists(resourceFolderPath)) 97 { 98 Directory.CreateDirectory(resourceFolderPath); 99 } 100 101 AssetDatabase.CreateAsset(paths, resourceFolderPath + "/ResourcePaths.asset"); 102 paths.paths = ResourcePathUtility.GetResourcePaths(string.Empty); 103 EditorUtility.SetDirty(paths); 104 AssetDatabase.SaveAssets(); 105 } 106} 107#endif
他のスクリプトでは、下記のように使うことで子項目の名前が得られるかと思います。
C#
1var childNames = ResourcePathUtility.GetChildNames("images/characters");
投稿2022/02/16 11:32
総合スコア10816
1
それをする方法はありません。System.IO を使ってディレクトリにアクセスすればできるという回答がネットにちらほらありますが、それは Unity Editor 上でだけ有効で、ビルドしたらフォルダ構成というものはなくなるので機能しなくなります。
どうしてもそれをやりたい場合は、Unity Editor 上で(つまりビルドする前に)プロジェクトのフォルダ・ファイルのディレクトリ構成を別途ファイルに保存しておき、実行時にはそのファイルから欲しい情報にアクセスする、というやり方でしのぎます。
投稿2022/02/16 03:52
総合スコア5339
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。