Projectで選択したフォルダー以下の.prefabファイルと保存フォルダーの構造を、ツリーとしてCSVへ書き出すEditor拡張です。Prefab内部のGameObjectやコンポーネントを調べたい場合は、内部構造のCSV出力を使います。
仕様の参照はUnity 6.3 LTSです。本文のCSV整形とツリー構築だけをWindowsの.NET環境で確認しました。Unity Editorでのコンパイル、Project選択、AssetDatabase検索、保存ダイアログ、実アセットの出力は未確認です。掲載画像は元記事の旧資料で、修正版の実行結果ではありません。

出力の仕様:1列CSVとPrefabを含むフォルダー
| 項目・症状 | 内容・確認先 |
|---|---|
| 対象 | Projectで選ぶAssets内のフォルダー1つと、その子フォルダーにある.prefab。PackagesやModel Prefabは対象外。 |
| 1列のCSV | ヘッダーはツリー。選択したアセットパスをルート行にし、フォルダーとPrefabを枝記号で表示。 |
| 表示するフォルダー | 見つかったPrefabの保存階層に必要なフォルダー。Prefabがない空フォルダーは省略。 |
| 並び順 | フォルダーを先、Prefabを後とし、それぞれOrdinalの文字列順。自然順やExplorerと同じ並びを保証しない。 |
| 取得しない情報 | Prefab内部のGameObject、コンポーネント、ファイルサイズ、更新日時、参照関係は出力しない。 |
次の画像は旧版の表示例です。修正版では選択フォルダーのアセットパスをルート行へ入れ、Prefabに関係するフォルダーだけを残します。旧画像と同じ行が出るとは限りません。

Assets/Editorへコードを保存する
- プロジェクトを複製し、Assets/Editor/PrefabTreeCsvExporter.csへ下のコード全体を保存します。GameObjectへ追加するコンポーネントではありません。
- 旧PrefabTreeCsvExporterがある場合は置き換え、同じクラスやメニューを2つ残さないようにします。
- asmdefを使う構成ではEditor専用Assemblyへ入れ、UnityEditorをPlayer用へ含めない設定を確認します。Editorフォルダーの公式説明も参照してください。
- Unityへ戻りConsoleのコンパイルエラーを確認します。Tools → 選択フォルダ以下のPrefabツリー構造をCSV出力のメニューが出るか確認します。
フォルダーを選び、保存結果を確認する
- 最初はAssets内の小さなフォルダーを用意し、直下と子フォルダーに1つずつPrefabを保存します。Prefabがないフォルダーも作ると、省略される条件を確認できます。
- Projectでそのフォルダー1つだけを選択します。HierarchyのGameObject、Prefabファイル、複数フォルダーの選択は、この例の入力にしません。
- メニューを実行し、保存ダイアログでCSVの保存先とファイル名を指定します。旧版の保存先フォルダー選択から、ファイル保存ダイアログへ変更しています。キャンセルすると保存せず終了します。
- ConsoleのPrefab件数と、CSVのPrefabファイル行を照合します。CSVにはヘッダーやフォルダー行もあるため、全行数をPrefab件数として数えません。
- 日本語やカンマを含む名前、複数の枝、同名Prefabの異なる保存先などを加えて、取込後も1列のツリーとして読めるか確認します。
例えばAssets/PrefabsにA.prefabとSub/B.prefabがある場合、修正版はAssets/Prefabsをルートにして、Subの下にB.prefab、直下にA.prefabを配置する構成です。これは構成したパスを用いた整形確認の例で、実PrefabをUnityから出力した検証画像ではありません。
旧版の出力資料との違い
次のコードブロックは、元記事にあった旧ツリー例を保存したものです。旧版は最上位を/として選択フォルダー名を省略し、Prefabのないフォルダーも走査していました。修正版の正確な出力例としては使いません。
/
└─ Prefabs
└─ sample
├─ sample 1.prefab
├─ sample 2.prefab
└─ sample 3.prefab元記事の画像も旧版の資料として残しています。今回の修正版では保存ダイアログとルート行、空フォルダーの扱いを変更しています。

修正版コード全文
PrefabのパスはAssetDatabaseから取得します。Application.dataPath全体からAssetsという文字を削除する処理や、物理ディレクトリの再帰探索は使いません。Prefabの内部も読み込まず、見つかったアセットパスからツリーを構築します。
using UnityEngine;
using UnityEditor;
using System;
using System.IO;
using System.Text;
using System.Collections.Generic;
public static class PrefabTreeCsvExporter
{
[MenuItem("Tools/選択フォルダ以下のPrefabツリー構造をCSV出力")]
public static void Export()
{
UnityEngine.Object[] selected = Selection.objects;
if (selected.Length != 1)
{
Debug.LogWarning("ProjectでAssets内のフォルダーを1つだけ選択してください。");
return;
}
string folder = AssetDatabase.GetAssetPath(selected[0]);
if (!AssetDatabase.IsValidFolder(folder) || !(folder == "Assets" || folder.StartsWith("Assets/", StringComparison.Ordinal)))
{
Debug.LogWarning("Assets内のフォルダーを1つ選択してください。");
return;
}
var paths = new SortedSet<string>(StringComparer.Ordinal);
foreach (string guid in AssetDatabase.FindAssets("t:Prefab", new[] { folder }))
{
string path = AssetDatabase.GUIDToAssetPath(guid);
if (path.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase)) paths.Add(path);
}
if (paths.Count == 0)
{
Debug.LogWarning("選択フォルダー以下に.prefabが見つかりませんでした。");
return;
}
string savePath = EditorUtility.SaveFilePanel("PrefabツリーのCSVを保存", "", "Prefab_Tree_" + DateTime.Now.ToString("yyyyMMdd_HHmmss"), "csv");
if (string.IsNullOrEmpty(savePath)) return;
try
{
List<string> lines = PrefabTreeCsvFormatting.BuildLines(folder, paths);
var csv = new StringBuilder();
csv.Append(PrefabTreeCsvFormatting.Csv("ツリー") + "\r\n");
foreach (string line in lines) csv.Append(PrefabTreeCsvFormatting.Csv(line) + "\r\n");
File.WriteAllText(savePath, csv.ToString(), new UTF8Encoding(true));
Debug.Log("PrefabツリーCSV保存完了: Prefab " + paths.Count + "件\n" + savePath);
}
catch (Exception e) { Debug.LogError("PrefabツリーCSV保存失敗: " + savePath + "\n" + e); }
}
}
public static class PrefabTreeCsvFormatting
{
private sealed class Node
{
public readonly SortedDictionary<string, Node> Folders = new SortedDictionary<string, Node>(StringComparer.Ordinal);
public readonly SortedSet<string> Files = new SortedSet<string>(StringComparer.Ordinal);
}
public static string Csv(string value)
{
return "\"" + (value ?? "").Replace("\"", "\"\"") + "\"";
}
public static List<string> BuildLines(string rootPath, IEnumerable<string> paths)
{
if (string.IsNullOrEmpty(rootPath)) throw new ArgumentException("ルートを指定してください。");
rootPath = rootPath.TrimEnd('/');
var root = new Node();
foreach (string path in paths)
{
if (string.IsNullOrEmpty(path) || !path.StartsWith(rootPath + "/", StringComparison.Ordinal)
|| !path.EndsWith(".prefab", StringComparison.OrdinalIgnoreCase)) continue;
string[] parts = path.Substring(rootPath.Length + 1).Split('/');
if (parts.Length > 257) throw new InvalidOperationException("保存階層が深さ256を超えました。");
Node node = root;
for (int i = 0; i < parts.Length - 1; i++)
{
Node next;
if (!node.Folders.TryGetValue(parts[i], out next))
{
next = new Node();
node.Folders.Add(parts[i], next);
}
node = next;
}
node.Files.Add(parts[parts.Length - 1]);
}
var lines = new List<string> { rootPath };
Render(root, "", lines);
return lines;
}
private static void Render(Node node, string indent, List<string> lines)
{
int count = node.Folders.Count + node.Files.Count;
int index = 0;
foreach (KeyValuePair<string, Node> folder in node.Folders)
{
bool last = ++index == count;
lines.Add(indent + (last ? "└─ " : "├─ ") + folder.Key);
Render(folder.Value, indent + (last ? " " : "│ "), lines);
}
foreach (string file in node.Files)
lines.Add(indent + (++index == count ? "└─ " : "├─ ") + file);
}
}
ツリー構築とCSV整形で確認した範囲
掲載した整形クラスを.NETでコンパイルし、直下のソート・重複除外、子と兄弟、フォルダーの連鎖、範囲外と非Prefabの除外、日本語・カンマ、空入力の6ケースを確認しました。深さの制限を超える構成したパスがエラーになることも確認しています。
CSVは1行を一つのフィールドとして引用します。名前にカンマ、引用符、改行がある構成した10入力で、C#が作ったフィールドをPythonのCSV読取で元へ戻せることを確認しました。この確認にUnityの検索・出力操作や表計算ソフトの画面操作は含めていません。
ファイルはUTF-8のBOM付きで保存するコードです。表計算ソフトではCSV取込を使い、文字コードと列の型を確認します。CSVは表計算のブック形式ではなく、ツリー文字列を1列に置いた形式です。名前や枝記号が勝手に変わる場合は取込時の自動変換を調べます。
メニュー・検索・保存でつまずく場合
| 項目・症状 | 内容・確認先 |
|---|---|
| メニューが見つからない | Consoleのコンパイルエラー、Editor専用の配置、.cs拡張子、旧コードの重複を確認。 |
| 選択の警告が出る | ProjectでAssets内のフォルダーを1つだけ選ぶ。ファイルや複数フォルダー、Packagesを混ぜない。 |
| Prefabが見つからない | 選択範囲に.prefabがあるか、Importされているかを確認。FindAssetsの検索範囲は指定フォルダーと子。 |
| フォルダーが出力にない | Prefabがない空フォルダーは省略する仕様。全フォルダーの棚卸しとは分ける。 |
| 保存できない | Consoleの保存失敗と例外、保存先の権限・ファイル利用状態を確認。保存失敗を成功として表示しない。 |
| CSVが複数列になる | 全フィールドの引用を保って読む。単純なカンマSplitではなくCSVの読取・取込機能を使う。 |
| 内部のGameObjectが見えない | この例は保存階層の出力。Prefab内部CSVの記事へ進む。 |
検索後にアセットを移動・削除した場合の再取得、非常に大きい一覧の進捗・キャンセル、JSONや参照関係への拡張は含めていません。目的がファイル階層の確認を超える場合は、必要な列と動作を追加する別の設計にします。
既存の元コードの配布先では01.txtが旧例、02.csが旧版のコードです。本文の修正版とは異なり、ここでは外部リポジトリを更新していません。Prefabの内部構造や撮影を扱うEditor拡張は次の記事で確認できます。
エディタ拡張の記事は、ほかにもあります。




