UnityのPrefabの差分を、Hierarchy・Scene・Inspectorで確認できるエディター拡張「Prefab Diff Viewer」を作りました。
左にHierarchy、中央にScene、右に変更前後のInspectorを並べています。
AIにPrefabを任せると、変更の確認が難しかった
最近はUnityの開発をAIに任せることが増え、C#だけでなくPrefabの配置や設定も修正してもらっています。
ところが、修正後のPrefabをUnityで開いても、どのGameObjectの、どの値が変わったのかはわかりません。見た目が合っていても、意図しない変更を見落とすことがあります。
テキスト形式のPrefabならGitで差分を確認できます。ただ、次のようなYAMLを見ても、それが画面のどの部分なのかを読み解く必要があります。
Gitでは値や参照の変更を追えますが、GameObjectの名前や親子関係をたどる必要があります。
Unityで普段見る形でレビューする
そこで、差分を次の流れで確認できるようにしました。
- Hierarchyで、追加・削除・変更されたGameObjectを探す
- Sceneで、選んだGameObjectの場所と変更後の見た目を確認する
- Inspectorで、変更された値を左右に並べて比較する
左が変更後、右が変更前。ScaleやSprite、Colorなどの変更箇所に色を付けています。
たとえば上の例なら、ScaleのX・Yが1から1.5に、Spriteがenemy_slimeからicon_heartに変わったことを確認できます。
実装で工夫した3つのこと
1. 名前ではなくfileIDで対応付ける
Unityのテキスト形式では、GameObjectやコンポーネントがそれぞれYAMLドキュメントとして保存され、fileIDで相互に参照します。Unity公式:テキスト形式の構造
GameObjectのm_ComponentとTransformのm_Father・m_Childrenをたどって、Hierarchyを組み立てます。変更前後で同じfileIDを持つものを対応付けると、名前や親が変わっても同じオブジェクトとして追えます。
外部ツールがIDを振り直した場合は、削除と追加として扱う限界があります。
2. YAMLの差分をInspectorの欄に結び付ける
設定値は、次のようにプロパティのパスと値に展開して比較します。
m_AnchoredPosition: {x: 0, y: -192}
↓
m_AnchoredPosition.x = 0
m_AnchoredPosition.y = -192
UnityのSerializedProperty.propertyPathに合わせることで、YAMLの差分をInspectorの対応する欄に結び付けやすくしました。Unity公式:SerializedProperty
また、数値の1と1.0のような表記だけの違いは通常の変更と分けています。一方、文字列の"1.10"→"1.1"は表示内容が変わるため、Unity側の型情報も確認します。
3. 保存された値と、読み込み後の値を分ける
Layout Groupなどが位置やサイズを決めるUIでは、ファイル上の値が変わっていても、Unityで読み込むと再計算されることがあります。
そうした変更は灰色で表示し、通常の変更件数とは分けました。Inspectorには読み込み後の値を出し、ツールチップにはファイル上の変更前後の値を出しています。
変更前の表示は、Gitから取得したYAMLを一時的なPrefabとしてインポートし、PrefabUtility.LoadPrefabContentsで読み込んで作ります。表示用コピーの編集は元のPrefabには保存しません。Unity公式:LoadPrefabContents
ただし、スクリプトや画像まで過去の状態に戻すわけではないため、現在のプロジェクトにない参照先はMissingになります。
AIが作った変更を、自分で理解するために
AIに任せる範囲が広がると、レビューする対象もPrefabやシーンへ広がります。
どのGameObjectが変わり、見た目や設定にどう影響したのか。 それを普段のUnityの操作に近い形で確認したくて、このツールを作りました。
ただ、そもそもプログラムやPrefabを人間がレビューする必要があるのかは、私自身も悩んでいます。
今はAIを使った開発の過渡期で、これから開発手法そのものが変わり、今のようなレビューの仕組みも変わっていくと思います。
これから、どんな開発スタイルになっていくんでしょうね。時代の流れにアンテナを張りながら、柔軟に対応していきたいです。

