YAMADA TAISHI’s diary

ゲームについてとか私の日記とか。このブログのあらゆるコードは好きにどうぞ。利用規約があるものは記事内のGitHubのRepositoryのリンクで貼られていると思うので、そちらを参照ください。

Unityでmetaファイルごとコピーをするな!

こんにちは、やまだたいし( https://twitter.com/OrotiYamatano )です。
Unityではmetaファイルごとコピーすることで不都合が生じます。
Unityでmetaファイルをコピーすると生じる不都合はどのようなものなのか、
なぜ発生するのか理屈を分かりやすく説明していきます。


目次


なぜmetaファイルのコピーが問題になるのか?


皆さん、Unityで作業をしているときに、gitから落としてきたデータが毎回metaファイルの差分が出る、
または自分が上げたデータが他の人の環境でMissingになることはありませんか?

この問題はmetaファイルを正しく管理できていないことが原因です。
今回は、metaファイルをコピーすることで生じる不都合とその理由について詳しく説明していきます。

metaファイルとは?


UnityではAssetを扱う場合、
アセット本体とmetaという参照情報などを格納している2つのファイルで管理しています。

metaファイルはyamlという形式で書かれ、中身は文字情報になっています。
中にはその本体ファイルのIDやファイルフォーマットバージョン、本体ファイルに何がアタッチされているのか、などといった情報(メタ情報)が入っています。

本体ファイルのIDはUUIDとも呼ばれ、Unity上で自動的に割り当てられます。
ちなみに参照情報をテキストではなくバイナリで扱ったほうがインポートが早いなどのメリットもありますが、
テキスト形式の方がgitなどのバージョン管理ツールを使ったマージが容易です。

昔はバイナリファイルでも管理が可能でしたが、ほとんどの場合で競合が発生するため、
ユーザーの多くがテキスト形式を使用していました。そのため、バイナリ管理はエディタ上から姿を消しました。

metaファイルのコピーによる具体的な問題


UUIDの重複とその影響


なぜmetaファイルと本体をそのままコピーしてはいけないのか。
本体だけであればunity にてインポート処理が走った際にmetaファイルが新規作成されるので問題ありません。

しかしmetaファイルごとコピーすると、同じUUIDを持つアセットが複数存在することになります。
これは、UUIDがUnity上で自動的に割り当てられるためです。UUIDは各アセットを一意に識別するためのものであり、重複すると問題が発生します。

UUIDが重複すると、Unityはどのアセットを正しく参照すべきか判断できなくなります。
この結果、以下のような問題が発生します:

具体例:3Dモデル、マテリアル、テクスチャを管理するプロジェクト


1. 元のプロジェクトの状態

  • プロジェクトには3Dモデル(guid:1234)、マテリアルA(guid:1235)、テクスチャ(guid:1236)が存在
  • それぞれにメタファイルがある

2 . metaファイルごとマテリアルをコピー:

  • マテリアルAをコピーしてマテリアルBを作成してしまう
  • metaファイルもコピーされ、guid: 1235が重複

(ローカルでは追加されたファイルだけがダーティフラグが立ってimportされるため問題ない)

3 . UnityがUUIDの重複を検出

(他の人の環境では参照が見つからなくなる)

  • こうなったとき再guidの割当が行われる
  • 他の人の環境ではimportが走り重複しているguidの再割り当てが行われる
    • 条件は私は知らないが場合によってはall reimportが走ってしまうようだ

再割り当ては追加されたfileが再割り当てされればよいがそうなるとも限らない
↓こうなってしまう場合も

  • Unityはどちらのマテリアルを参照すべきか判断できず、また複数同じguid参照ある場合Missingになる可能性も

じゃあなぜ現場ではmeta毎コピーが多発するのか


不具合が出るのは理解いただけただろう。
じゃあなぜ、デザイナーさんなどはmeta毎コピーをしてしまうのだろうか。
それはUnityでのコピー問題である。

例えば貴方が先程のモデルの色差分データを作ることになったとしよう。
モデルはそのまま利用すればよく、 差分データなので、マテリアルとテクスチャのコピーを作れば良い。

Unity上でコピーをすると以下のようなデータになる。

なぜか参照が古いものを指しています。 これはUnityのコピーは基本シャローコピー(浅いコピー)と呼ばれるものだからです。

では、エクスプローラー上でコピーした場合はどうなるだろうか。 実は一見正しくコピーされたかの様な挙動をしめします。

しかし、他の方がプロジェクトを開くとguidの不一致によりmissingになったりします。

解決策


では、どうしたら良いでしょうか? いくつか、方法があります。

1.Unity上でコピーした上でなおす

これが一番妥当です。
コピーしたリソースは参照エラーが出てしまいますが、これを一つ一つなおすのが正解です。

2.破壊される前提でコピーした後になおす

どれがどう紐づいていたか分からなくなってしまいなおすのが大変です。
正気の沙汰ではないですが、他の人は問題なく動作します。

3.プログラマーにディープコピー機能を作ってもらう

作る手間はありますし、どの程度参照を取得するか迷いどころですが、こちらも一考です。
以下、ブログなどが参考になると思います。

小技


最後に小技を紹介して終わります。 Unityでは先程も言ったようにguidによって管理されています。 そのためリソース本体には参照が影響されません。 なので、エクスプローラー上でリソースの差し替えが可能です。 ぜひ、ご活用ください。

まとめ


以上です。
metafileの扱いには気をつけてください。