ゲームジャムが近いので、複数人開発で注意すべきことをまとめる。この内容は自分の開発経験やヒアリングを元に考えたものだ。※この方法が正しいとは限らない。とにかく意見がほしい
今回は管理システムにはGitでSource Tree、Unityのバージョンは4.5を想定。
ややこしい…、やるべき事だけ教えろ!って人のため、簡易版を用意した。
この取り敢えずこのルールを守っていればOKなハズだ。
Unityで複数人で開発する際に注意すべき事(簡易版) - テラシュールブログ
- バージョン管理システムを覚える
- プロジェクト設定で注目すべきポイント
- .metaファイルが更新されるケース
- 機能の追加フロー(Unity 5.2、Unity 4向け)
- 文字コードに気をつける
- コミットで気をつける
- プッシュ・プルが失敗するケース
- 競合してしまった場合の対処法
- アセットサーバーやSVN・Gitに繋がらないケースの対処法
バージョン管理システムを覚える
ゲームジャム・ゲーム開発で、Gitやバージョン管理システムが使えない人がいるとかなり足手まといになりやすい。特に、ゲームジャムのように展開が高速で物事が進む上に客員に余裕が無い場合、バージョン管理に参加出来ない人がグラフィックやシステムを作っても、最終的にゲームに組み込まれない事が多々ある。
Gitの操作方法については、【連載Git目次】ほんとは簡単?SourceTreeでGitを始めよう! が超詳しくてわかりやすいのでお勧め。
ゲームジャム中に使い方に困ったら、とりあえず誰かに聞けば大体答えてくれるはず。

上で紹介した記事は素晴らしく、面倒でも読んでおいた方が良いが、時間がない場合はココからSourceTreeをインストール後 とりあえず5つのことを覚えておこう。
コミット
自身の端末で行った新規素材の登録( )や変更 (
) ・削除(
)を確定する。大抵はコミットしたいファイルを選択してコミットボタン。もしくはステージ(コミット対象一覧)へファイルを登録してコミットボタン。AssetServerやSVNの場合は、一緒にプッシュも実行される。
リセット
自分の変更を破棄して、ファイルを最後にコミットした状態まで戻す。
新規アイテムにはリセットではなく削除を行う。
AssetServerではdiscard。
プッシュ
コミットした内容をアップロードして、リポジトリを更新する。
他の誰かがプッシュしていた場合、失敗する。その場合、一旦プルで自身の環境を最新の状態にしてからプッシュする。
プル
プッシュによるプロジェクトの変更をダウンロードしてローカルに反映。
プルで更新されるファイルを自身がローカルで更新していると、失敗する。
プルで更新されるファイルを既にコミットしていた場合、競合が発生する。
マージ(解決)
プルで他人のコミットと自身のコミットが競合( )した場合、どちらのコミットを採用するかを決定する操作。 お互いの変更点を取り出すケースもある。
プロジェクト管理の問題は大体コレが原因。
AssetStoreのアセットをオープンソースに含めたい - テラシュールブログ
unitypackage以外でファイルを受け渡す場合、渡された人が必ずコミットする。間違っても複数人に渡してはいけない、メタファイルが複数種類生成され、プロジェクトが混乱する。
unitypackageでファイルの投げ合いでプロジェクトを進める場合、dropbox等で管理すると「最新」が分かりやすいので非常に良い。バージョン管理より強引な手法だが、ひとまず「最新の状態を維持」出来る。オススメはしない。
ちなみにファイル名に日付を付けて管理する奴は私は嫌いだ。
VSSの中に日付名のzipを付けて管理してる奴は一番嫌いだ。
プロジェクト設定で注目すべきポイント
Unityでプロジェクトを作成する上で行うべき事は2つ。
Unityのバージョンを(マイナーバージョンを含め)統一する事と、metaのフォーマットをforce textに設定することだ。
まずUnityのバージョンを統一する事は非常に重要だ。Unityはある程度は下位互換・上位互換が保たれているが、バージョンの違いによっては変換が必要なものがある。特にシーンやメタファイルのパラメータはエディタのバージョンによって微妙に違う事があるので、これを合わせていないと無駄に変換が走る。兎に角、複数人で開発を進める上で複数のバージョンを持つことは非常にリスクだ。APIも違うし、変な設定ファイルができちゃうし。
もう一つ、metaのフォーマットをforce textに設定しておく事。こうする事で、prefabやsceneといったバイナリフォーマットのファイルをテキストで確認する事が出来る。 シーンのマージは致命的に難しいが、絶対できないよりは出来たほうがマシだ。 prefabのマージは意外となんとかなる。
force textに設定するには、[メニュー] -> [Edit] -> [Project Settings] -> [Editor] を開いて、[Asset Serialization]を[Force Text]に設定する。これをするのは、ベースとなるプロジェクトだけで良い。ちなみにForceTextは最近のUnityなら無料版でも使える。

gitで管理する場合、以下の項目をignoreに追加しておく。この項目はなにか変更する度に変更される上、.metaやソースコードさえあれば問題なく動作する箇所。
[Ll]ibrary/
[Tt]emp/
[Oo]bj/# Autogenerated VS/MD solution and project files
/*.csproj
/*.unityproj
/*.sln
/*.suo
/*.user
/*.userprefs
/*.pidb
/*.booproj
.metaファイルが更新されるケース
metaファイルは、Unityプロジェクトにインポートした際に生成され、プロジェクト上でのファイルの振る舞いについての情報を持つ。 例えば、Textureの圧縮フォーマット、Modelの設定等々。
また、プロジェクトからファイルを参照するために必要なUUID(ユニークなID)を保持するのもコレ。その為、何らかの理由によりmetaファイルが再生成されUUIDの値が変化してしまった場合、Unityプロジェクトからの参照がmissingになってしまう。
メタファイルが生成・破棄されるパターンは以下のとおり。
Unity Project以外からファイルを移動・リネームする
FinderやExprolerからファイルを操作した場合、Unityエディタは「ファイルが無くなった」と判断し、現在のmetaファイルを削除・新しいメタファイルを作成する。
metaファイルが無い
例えばAssets直下に何らかのファイルを配置した場合、ファイル名+.metaのファイルがない場合は自動的にファイル名+.metaのファイルを作成する。このため、metaをコミットせずプッシュしてしまうと客員がmetaを生成する大惨事になる。
metaファイルの元ファイルが無い
メタファイルの参照元のファイルがない場合、メタファイルは削除される。この判断は「***.meta」の***と同名のファイルの有無で行う。
その為、メタファイルだけ残してファイルを更新する事で、ファイルの上書きが可能。
逆に、メタファイルが更新されるパターンは単純で、Unityエディタからファイルのパラメータを変更するとメタデータが更新される。
例 えばテクスチャの設定をTextureからSpriteに変更するとメタデータが更新される。このようなケースの場合、メタデータを更新しないとプルした 人はうまく動作しないかもしれない。メタデータのコミット忘れにはよく注意する。またラベルも同様にメタデータに格納されている。
メタファイルが上書き保存されるタイミングは、シーンの保存やSave Projectでプロジェクトを保存か、Unity Editorの終了のタイミング。そのため、これを行っていない状態でエディタがクラッシュして落ちると.metaデータが古いままのケースがある(場合によってはプレハブの中身がなくなる)。これはプレハブはエディタ拡張で自動更新させる事である程度の緩和が可能だ。例えば前に作ったシーンの自動バックアップ機能だと、一定時間毎にメタファイルを更新する。
Unityに自動セーブ機能を追加してみた - テラシュールブログ
ちなみに、ファイルを上書き更新したい場合はFinder・Explorerで直接ファイルを上書きする。これは何故かUnityのProjectビューではファイルを上書きできない謎仕様の対策の一つで、metaファイルがあり同名のファイルがあればmetaが新しく生成されない点を利用したトリック。Unityはどちらかと言えば直接編集する事を想定している臭い。
これは「同名のファイルがドラッグ&ドロップで追加された場合は上書きするスクリプト」を導入すれば回避可能ではあるが、末尾数字のファイルには使えない等の問題があるので、Finderを使用することをお勧めする。
もう一つ、gitでバージョンコントロールを設定する際に複数人のメタファイルに対する設定が異なる場合、プルした度に毎回違う内容が返ってくる事がある。例えばForceTextにしている人とBinaryで設定している人がいた場合、メタファイルが自動的に変化してしまう。また、Version Controllの設定がmetaの人とasset serverを設定している人がいた場合。これもメタファイルが変化してしまう。(勝手にメタファイルが変わると勘違いしている人は大体これが原因。次点でUnityエディタのバージョンが異なる人がいる)
基本的に(エディタ拡張でメタファイルを更新する機能を持っていない限り)メタファイルが勝手に変化する事はないので、そのあたりをよく注意する。
機能の追加フロー(Unity 5.2、Unity 4向け)
機能を追加する場合、以下のフローで作成する。
ゲーム用のシーンが非常に複雑だったり、ステージ等・長時間の調整が必要な場合は、シーンを分割して実行時に結合するようにする。
- 機能をテストする用のシーンを作成
- 1で作成したシーン内で機能を作成する
- ゲーム用のシーンに組み込む
- コミット(&プッシュ)
なお、この方法はステージに配置したギミックがそれぞれ独立して動くような形にする必要がある。というのもシーンのロードは即座に読み込まれる物ではないため、オブジェクト同士の連携タイミングが若干難しいからだ。こういった場合にはNortificationObjectやNotificationCenterといった、通知センターの活用が有効だ。
値の変更を通知するクラス
Unity WIki Tips - メッセージ通知センター
ゲームマネージャー等、何処のクラスからもアクセスされる物に関してはプレハブ化して、その項目をマージしていくのも有効だ。その場合、プレハブの競合には十分注意する。
この「3. ゲーム用のシーンに組み込む」の際は特定の人に一任する手もある(チームのリーダー等)。その場合、チームリーダーが既存のシーンに組み込みやすいように、1で作成するテストシーンはわかりやすくすると良さそうだ(コンポーネントのコピーで可能にする・プレハブ化する等)
ま たSVNやVSSのようなファイルをロック出来るシステムをバージョン管理に使用している場合、シーンを編集する際にロックすることで3の作業中に他の人がシーンを編集する事を防ぐことが可能だ。これはチームリーダー以外でもゲームシーンを操作する場合に有効だ。その場合、エディタ拡張で何らかのサービス・ファイルを確認し、 アクセスを視認出来るようにするのが良さそうだ。
1で作成する「テスト用シーン」は、作業するユーザー名のテスト用フォルダを用意し管理するような形にすると、プロジェクトを汚さず比較的シンプルな状態を保つことが出来る。これはブランチを切っても良い。そこでしか使わないスクリプトがある場合、シーン名のフォルダを作って管理するとより分かりやすい。またラベル管理しても良い。
文字コードに気をつける
開発チーム内にWindowsとMacが混在する場合、文字コードに注意する。文字コードがUTF-8のBOM付き以外の場合は、Windowsだと日本語コメント後に「.(ドット)」を付与しないと、次の行が無視されるバグがある。
[Unity][Unity3d]UnityでC#の新規作成ファイルをBOM付きUTF-8にするコマンド(Mac環境向け)や、スクリプトファイルのutf-8変換を使用してプロジェクト内の文字コードを何とかするか、「.(ドット)」を日本語コメント末に付与して回避する方法が上げられる。
コミットで気をつける
コミットする場合、基本的に自分の変更を反映させるために必要なファイルのみをコミットする。割とよくあるのが、変更点全てコミットされるケースだが、これを多用する人がいると競合が多発するので非常に面倒くさい。コミットを「無かったことにする」のは割と面倒くさいので、コミットする場合は慎重に行うべきだ。ちなみにソースのコミットであれば行単位で出来る。

コミットで一点注意すべきもう一つの事は、ファイルをコミットする際、メタファイル(.meta)を一緒にコミットする事だ。.metaファイルはAssetsフォルダ以下にファイルを配置した際にファイル名+.metaという形で別途生成される。メタファイルはファイルの参照やパラメータを管理するファイルなので、必ず忘れずにコミットする。

もしプロジェクトをプルした後に.metaが生成されているケースがあった場合、誰かが.metaをコミットしていない。その場合、その誰かにメタファイルをコミットしてもらい、ソレ以外の開発者はメタファイルをリセットして無かったことにする事が最も良い方法だ。間違っても.metaの新規ファイルをコミットしてはいけない。
もう一つあった。コミットする前にシーンを保存するかエディタを終了かprojectを保存する事をお勧めする。理由は上にも書いたがプレハブファイルの更新タイミングがそのタイミングだからだ。その為、これを行わないとプレハブやメタデータが更新されていないケースが発生する。
プッシュ・プルが失敗するケース
これはゲームジャムで必ず発生するケースだ。
開発中にプッシュに失敗するケースがある。その場合、大抵の原因がプルが必要なのにプッシュしようとするケースだ。バージョン管理システムに置いては、同一ブランチでは常に最新で開発を進めるため、プル出来る項目がある場合はプッシュ出来ない。もし問題なくプル出来ればプッシュできるようになる。

もう一つの可能性は、プッシュする権限がないケースだ。その場合は、プルリクエストを送信するか、権限を付与してもらう。この辺りはちゃんとエラーメッセージに出るので、それを良く確認する。
プル出来ないケースは、大抵の場合はプルで更新されるファイルをローカルで更新しているケースだ。例えば下の例の場合、README.mdの変更をプッシュした状態で他の人がREADME.mdを変更している。
この場合、競合しているファイル一覧を取得してリセット(discard)を行うことで競合を解決出来る。


外部マージツール(Win marge等々)が無い場合はマージが出来ないので、相手か自分の変更を適応する。
競合してしまった場合の対処法
追記:
Unity5よりシーンやプレハブのマージが可能になりました。
tsubakit1.hateblo.jp
複数のコミットが競合した場合、作業を続行するにはマージが必要となる。
マージするには、コンフリクトしたファイルを選択し、競合を解決→相手か自分の変更を使って競合を解決する…を選択する。とりあえず外部マージツールによる解決が難しい場合「相手の変更を使って競合を解決」が基本。
外部マージツールを使えば、もう少し細かい単位でマージすることが出来る。

シーンのマージは非常に面倒だ。単純な構造同士・パラメータの違い程度ならばマージする事は可能だが、親子関係の変化や複雑な参照が絡むと途端に難しくなる。
一応アセット等でシーンをマージしたり、リフレクションを駆使してシーン構造を取得・差分を作成して適応…のような事は可能だが、非常に面倒なので運用レベルでカバーするのが一番ラクだ。その辺りは今テスト中なので、成果が出たら公開する。
プレハブのマージはシーンマージよりは簡単だが、階層が深くなると理屈上は可能だが現実的に難しくなるので、nested prefab等の方法で階層が深くならないようにしたり、外部からパラメータを自動調整するような形にしておく。
完璧な作戦ッスねぇー、不可能という点を除けばよぉ
アセットサーバーやSVN・Gitに繋がらないケースの対処法
アセットサーバーがつながらない場合、接続対象のサーバーにアクセス出来ないケースが大体の理由だ。その場合はpingを飛ばす等で同一ネットワーク内にアセットサーバーを構築したPCがある事を確認する。
大学やネカフェ等、同一のゲートウェイを持っていても相互接続できないケースもある。そんな場合は、特定のPC(優先LANが繋がる奴)をホスト機にして他のPCから繋ぐような形で接続すると接続可能だ。
もしくはBitbacket等のサービスを使用すると吉。ただしSSL等の設定は面倒。
[Unity3D]Unity+Bitbucket(git)でプライベートリポジトリを使ってみた
Gitの場合は大体SSLが問題になるので、その辺りをよく調査する。この手の問題はログを読もうとするよりGoogle先生に直接問い合わせたほうが早い。
意見・要望は大歓迎。@tsubaki_t1まで
この記事のRT・ブクマ数見て後編の「複数人開発におけるお勧め設計・アセット管理」的なやつを書く予定