この記事はアピリッツの技術ブログ「DoRuby」から移行した記事です。情報が古い可能性がありますのでご注意ください。
はじめに
こんにちは motsukaです。
みなさんUnityを使うとき何気なくオブジェクトをプレハブ化して使っていますよね?
ですが、その中身がどうなっているかなんて知らないで使っている人が多いんじゃないですか?わたしは実際どうなっているか知りませんでした。
ですが、UnityをGit管理しているとき、よくプレハブがコンフリクトを起こしてしまって手動でマージしないといけない時、適当なエディタでファイルを開きますよね?
その時の構造を知れば、もっと安全に修正ができるとは思いませんか?
ということで、中身を読んでいきたいと思います。
GameObjectを読む
では下準備として、インスペクター上で新しくゲームオブジェクトをつくり、それをそのままプレハブとして保存します。
その保存したプレハブをテキストエディタで開いてみましょう。
そうすると、以下のようになっています。
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1001 &100100000
Prefab:
m_ObjectHideFlags: 1
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications: []
m_RemovedComponents: []
m_ParentPrefab: {fileID: 0}
m_RootGameObject: {fileID: 1000012251039328}
m_IsPrefabParent: 1
--- !u!1 &1000012251039328
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 4
m_Component:
- 4: {fileID: 4000012487135774}
m_Layer: 0
m_Name: GameObject
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &4000012487135774
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1000012251039328}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 2464.8406, y: 272.8769, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
では、上から見ていきましょう。
上から2行はただのヘッダーですので、気にしないでいいです。
3行目の !u!1 &6 とは、基本的にコンポーネントの切れ目に存在するもので、!u!の後の数字は オブジェクトクラスというUnityに割り振られたオブジェクトのIDが書かれています。このIDを使ってこのオブジェクトがなんなのかを判別しています。
&10010000は任意に名付けられるファイルIDでこの値を参照してどこのオブジェクトの子にいるのかなどに使われています。
その下からプレハブ内部の情報が書いてあります。
Prefab:
m_ObjectHideFlags: 1
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications: []
m_RemovedComponents: []
m_ParentPrefab: {fileID: 0}
m_RootGameObject: {fileID: 1000012251039328}
m_IsPrefabParent: 1
基本的にプレハブの参照関係が書かれています。
また参照 {fileID: 1000012251039328}は、
このファイルIDを参照していることを意味しています。
ファイルIDは、ファイル内でユニークな値ですので、違うファイルにも同じ値があることがあります。また、{fileID: 0} はどこにも参照していないことを示しています。
では、このプレハブが参照しているファイルIDのゲームオブジェクトを見ていきましょう
--- !u!1 &1000012251039328
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
serializedVersion: 4
m_Component:
- 4: {fileID: 4000012487135774}
m_Layer: 0
m_Name: GameObject
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
先ほど参照されていたファイルIDと同じものだということが1行目で確認できますね。
先ほど示したものはプレハブの情報だけしか載っていなかったのですが、ここからはゲームオブジェクトにくっついている様々なコンポーネントなどの情報が書かれています。
ここで大事な部分は、7行目のm_Componentの部分です。
これはこのゲームオブジェクトにどんなコンポーネントがついているかの参照が書かれています。
m_Component:
- 4: {fileID: 4000012487135774}
ここでは、オブジェクトクラスIDとファイルIDの参照が書かれています。
4という数字がオブジェクトクラスIDで、Unityのリファレンスで確認してみると、Transformということがわかります。
では、この参照されているTransformのファイルIDをファイルないから探してみましょう。
--- !u!4 &4000012487135774
Transform:
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1000012251039328}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 2464.8406, y: 272.8769, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
これが参照されているファイルIDのオブジェクトです。
確かにオブジェクトクラスIDに示されえている通りTransformですね。
TransformなのでPositionやRotationなどの項目がありますね。
またm_GameObjectの参照を見てみると先ほど見ていたゲームオブジェクトに参照がされていることがわかります。
まとめ
いかがだったでしょうか?プレハブファイルが読めるようになるとgitでコンフリクトした時にも役に立つので皆さんも是非読んでみてくださいね。
興味のある人はSceneファイルも同じ形式で書かれているので読んでみるといいと思います。
もう少し詳しく知りたいなら、Unityマニュアルの
https://docs.unity3d.com/ja/current/Manual/FormatDescription.html
のところを読んでみると面白いと思います。