Unityの.metaファイルに書かれているguidについて

# 概要
この記事ではUnity上guidを使った仕組みと、仕組みを利用したTipsを紹介します。
*Tipsがメインになってますので、仕組みを知っている人はTipsまで読み飛ばしても問題ありません。*

# guidとは
今回は突っ込んだ詳細は知らなくても良いのでざっくりとした内容になりますが、要は他と被る事の無い32文字の文字列であり、UnityではAssetsディレクトリで管理するAssetファイル(シーンファイル・Prefab・スクリプト・ディレクトリ・リソース・etc)すべてにこのguidが割り振らており、Inspectorから他のPrefab等のAssetファイル参照時もAssetファイル内では単にguidが書かれています。

ちなみに、AssetDatabase.GUIDToAssetPathでguidからファイルパスを取得出来たり、AssetDatabase.AssetPathToGUIDでファイルパスからguidを生成出来ますが、別にファイルパスをguid生成時に使用しているわけではないので、重複していなければ適当な文字列でも問題ありません。

* *ただし、自前でguidを作るとどこで重複が発生するか不明なので、Unityの自動生成に任せるか、Unity上でツールを構築する方が安全です*

* *事前にAssetファイルをテキスト形式にしておきます(メニューのEdit -> Project Settings -> Editor -> Editor SettingsのAsset SerializationをForce Textへ)*

# .metaファイルとは
Assetファイルと対になった、Assetファイルのメタ情報(音の場合はkbps等、画像の場合はisReadableフラグ等)が書かれたファイルで、このファイルにguidも書かれています。

このファイルが無い時は初期値が書かれた状態で自動生成され、スクリプトやPrefabの時はメタ情報もguid程度しか書かれていない為、バージョン管理する際はこの.metaファイルも一緒に追加する、Assetファイルを操作する時はUnity上のProjectウインドウから操作する、というルールを守っていれば別段気にする必要はないです。

ただし、音や画像等のAssetファイルの場合は、上記に書いたように設定値となるメタ情報も書かれている為、大事なファイルになってきます。

また、Assetファイルを操作する時は、Projectウインドウから操作するのが普通になっています、というのも、ファイルのメタ情報を.metaファイルに記述している為、Unity管理外からファイルを操作するとこの.metaファイルが更新されず、設定値が壊れてしまう場合がある為です。

* *例えば、エクスプローラーからrenameした場合、.metaファイルが作り直される為、guidが再生成された為にInspectorのPrefab参照が外れたり、音、画像の設定値が初期化されたり*

# Tips
この記事のメインです、guidを利用した困った時に便利なTipsになっています。

## 参照しているPrefabを一括変更したい
たまーにあります、ここではUnixコマンドを使って対応します。

![sphere_prefab.png](https://qiita-image-store.s3.amazonaws.com/0/51728/ad8a97a4-c649-3c11-4ea1-4669486b7af7.png)


例えば、上の画像のSphere prefabが、testフィールドでtest prefabを参照している状態で、test_copy prefabに参照を変えたい、とします。

```
(ルートディレクトリがAssetsの場合)

置換元のguid
$ grep "guid" ./Prefabs/test.prefab.meta
guid: 7674e048f0903d7439bcd629d143d6bb

置換先のguid
$ grep "guid" ./Prefabs/test_copy.prefab.meta
guid: 51b5f5acbc1bc0f46bee74ffa692fa18

全てのprefabの、全てのguidを置き換える
$ find ./Prefabs -name "*.prefab" | xargs sed -i -e 's/guid: 7674e048f0903d7439bcd629d143d6bb/guid: 51b5f5acbc1bc0f46bee74ffa692fa18/g'

シーンファイル内も置き換えるなら
$ find ./Scenes -name "*.unity" | xargs sed ...
```

![sphere_prefab_after.png](https://qiita-image-store.s3.amazonaws.com/0/51728/9d514bf2-eeed-b390-518f-948a2948119a.png)



## フィールド名変更時、Inspectorの設定値が初期化されたのをもとに戻す

![sphere_rename.png](https://qiita-image-store.s3.amazonaws.com/0/51728/c472b9c5-4d21-fc81-cdc3-92fb0d69b769.png)

例えば、上の画像のSphereスクリプト内のtestを、renamedTestに名前変更したいとします。

![sphere_rename_before.png](https://qiita-image-store.s3.amazonaws.com/0/51728/1f0133b3-7ebc-14bb-435b-fc97e018474b.png)

Sphere.cs内のフィールド名を変更しただけだと、Assetファイル内には古いフィールド名のままで設定値が残り、新しいフィールド名の設定値が初期化されてしまいます。

古い設定値はそのままだと使われる事はなく、再設定、もしくは変更前とマージして復活させる、という手を使うしかないですが、それだと手間だし抜けも怖いです、もっと機械的に処理したい。

```
置換元スクリプトのguid
$ grep "guid" ./Scripts/Sphere.cs.meta
guid: cebfb56161901ff4d9f26830eac423ae

スクリプトのフィールド名部分を抜き出してフィールド名置換
$ find ./Prefabs -name "*.prefab" | xargs sed -i -e '/guid: cebfb56161901ff4d9f26830eac423ae/,/^---/{s/test:/renamedTest:/}'
```

別スクリプトの同名フィールドを省く必要があるので、対象スクリプトのフィールド名部分を範囲指定し、その中のフィールド名を置換しています。
ファイル内キーワードと重複の恐れがありますが、その時は重複エラーログが出るので、単にフィールド名置換で良しとしています。

* *重複エラーログが出てもビルドは通ってしまうので、厳密にするならキーワードには設定値がないのを利用して、test:.\\{2,\\}のように設定値があるかもチェックした方が良いです。*

![sphere_rename_after.png](https://qiita-image-store.s3.amazonaws.com/0/51728/12665725-dc9b-528b-6309-a6241aeb3b3b.png)


便利です


# やり残し

TipsはUnityから使えるコマンドにした方が利便性があがる。
(もしかしたらすでに誰かが別の手で解決してるのかも)