複数人でゲームを開発していると、同じファイルを同時に編集し変更内容が競合するケースがあります。
Unity5よりシーンやプレハブ編集ワークフローの見直しが入り、シーン構造の単純化やシーン・プレハブをマージするUnityYamlMergeの機能が追加されました。これにより同一シーン上で複数の開発者が同時編集、例えばステージとキャラクターギミックを編集し、最後に統合といったワークフロー も不可能では無くなりました。
ある程度は。
目次
Unity5のシーン構造の変化
Unityのシーン構造は、相変わらず「オブジェクト」と「コンポーネント」の情報のリスト構造です。
ただし、Unity5でシーンに依存する情報が減りコンフリクトが起こりにくくなるような幾つかの項目に修正が入りました。
プレハブの扱い
まずはプレハブのユニーク化(該当のシーンのみでプレハブに独自の値を設定)が無い場合、シーン内にプレハブの情報をシーンファイルへ書き込まずプレハブへの参照のみとなりました。
もしユニーク化している場合は、その部分だけシーンに記述されます。
元々シーンを読み込む際、プレハブのデータを確認し値が一致していなければユニーク化としてシーンの情報を使う…といった挙動を行っていましたが、これでシーン上でユニーク化したプレハブをガシガシ変更してもシーンのコンフリクトが起こりにくくなりました。
ただし元となるプレハブを削除してしまうとプレハブが「missing prefab」となってしまうので、注意が必要です。
ライトマップの扱い
ま たライトマップのUV情報等がシーンではなくLightmapSnapshotに格納されているっぽいです。単純に情報を外に出しただけの話ではあります が、コンフリクトの際にはこっちの方が良いんじゃないかと思います。auto(continues baking)でベイクした場合は何処にあるのかはわかりませんが…
UnityYamlMerge
マージする上で特に厄介と言われているのが「YAMLのオブジェクトを記述した位置が変化」するケースです。変化しただけならば何とかマージ出来るのですが、変化した部分が競合を起こすと非常に厄介な事となります。
例えば、AudioSourceコンポーネントのLoopにチェックを入れたブランチと、AudioSourceの順番が変更したブランチをマージするとします。この場合、Loopの変更とAudioSourceの順番変更で競合が発生します。これを解決するのは非常に骨が折れます。
そういったケースでは、Unity5より追加されたUnityYamlMergeが上手く動作します。このツールは「シーンの構造を解釈する」ツールです。単純な比較ではなくシーン構造を解釈することで、YAMLの要素の順番が入れ替わってもパラメータが競合していない箇所をマージし、パラメータの変更点だけを指摘してくれます。
UnityYamlMergeの設定方法
UnityYamlMergeの設定方法に関しては、以下のサイトが分かりやすく説明しています。
また、以下の記事も参考になります。
SourceTreeかつマージツールにP4Mergeを使用している場合は以下のように設定が出来ます。
- SourceTree>環境設定(Windows版はTool>Option)を開き、Diffタブを選択。
- Mergeコマンドに「/Applications/Unity/Unity.app/Contents/Tools/UnityYAMLMerge」と入力。
- 引数に「merge -p $BASE $REMOTE $LOCAL $MERGED」と入力。
- SourceTreeが開いているリポジトリのカレントフォルダ(普通のUnityプロジェクトならAssetsやLibraryと同じ階層)にautoという名前のファイルを追加(中身はテキスト)
- autoファイルの中身を「* use "%programs%/p4merge.app/Contents/Resources/launchp4merge" "%b" "%l" "%r" "%d"」に設定する。これはp4mergeの場合。
他のマージツールを使用したい場合は、/Applications/Unity/Unity.app/Contents/Tools/mergespecfile.txtの内容を元に書き換える。 - 後はプル中に競合したら「競合を解決>外部マージツールを起動」。パラメータの競合が無い限り綺麗にマージしてくれます。
た だしMacのSourceTreeはパラメータが競合した場合、マージツール起動後だいたい5秒後にマージを放棄してマージツールを終了する(しかも解決 扱い)というアホな不具合が発生している模様です。Windowsならば正常にマージできます。*1*2
現状Macでやる場合は、Mergeコマンド引数に「-o merge.txt」を付けて競合部分を確認、あとは自前でマージするのが良いかもしれません。自動マージは出来ませんが、手前でYAML読んでマージするよりずっと楽です。
merge -p -o merge.txt $BASE $REMOTE $LOCAL $MERGED
シーンやプレハブをマージする
実際にシーンをマージします。
- メニューバー > Editor > Project Settings > Editorを選択し、Asset Serializationの設定をForce Textへ変更します。
- Aさんは地面と赤・黄色のブロックのあるシーンを用意しコミットします。
- Bさんは2を取得・編集して、緑のブロックを追加しコミットします。
- Aさんは2からさらに編集して黄色のブロックを伸ばし、コミットします。
-
BさんAさんの変更をマージします。
と、このように各々が異なるオブジェクトに対し操作を行っている(パラメータが競合していない場合)は、素直にマージしてくれます。もし競合が発生した場合、「競合を解決>外部ツールを起動」すると、競合が解決されます。
ではパラメータが競合した場合はどうするのか。今度はプレハブで試してみます。下の図ではベースのプレハブからそれぞれ少しずつ変化を加えたプレハブをマージします。
結果、マージ可能な部分(xは両方共2、yはブランチ2しか変更していないので4)は自動的にマージされ、パラメータが競合を起こしているz値はユーザーの確認を求めてきます。
あとは普通に競合の解決を行えば、シーンがマージされます。
オマケ、2つのシーンを結合したい
シーンファイルを他のシーンファイルへドラッグ&ドロップすると、シーンのマージをが出来たりします。
- シーンをマージしたいシーンへドラッグ&ドロップします。
- Merge Into Exist(上書き保存)かMerge into new(シーンファイルを新規作成)かを選択します。
- Merge Tool Only(単純なマージ)か、Semantic and merge tool(構造を正しく解釈しマージ)を選択します。
- マージして保存、マージツールを終了させます。
- Acceptを選択してマージを終了します。
正直この機能は一貫性がなくバグなのかミスなのか機能なのかジョークなのか判断に迷う所ですが、知っていると割と便利です。
もう一歩進むと、マルチシーンエディティングが入る気がします。
関連情報
YAML構造について
複数人開発について