おもしろいもの、やくにたつもの を かきこむのだ!

【Unity Advent Calendar 2014】git subtreeを駆使して最強のUnityゲーム開発環境を作るぞっ!!

この記事はUnity Advent Calendar 2014の参加記事です。

Unityでゲームを作っていると
「前に作ったゲームの機能を新しく作るゲームでも使いたい!!」
コンポーネントのバグを直したから他のUnityプロジェクトにも反映したい!!」
ということがあるかと思います。

今回は、git のsubtreeという機能を使って、共通化して使いたいスクリプトコンポーネントを一元管理する方法について書きたいと思います。

共通で使っているソースコードコンポーネントをコピペやExport Packageを用いて他プロジェクトへ移すのが大変…(ヽ´ω`) という方にオススメかと思います。

git subtreeって何?

ざっくり書くと
「gitリポジトリ内に別のgitリポジトリをクローンしてきて取り扱う」 というものです。
git subtreeの詳しい話はこちらをご覧ください。

Unityでゲーム作る時にどうやって使うの?

  1. 自分で作ったスクリプトコンポーネントを一つのUnityプロジェクトにまとめる & gitリポジトリ化する(一元管理)
  2. ゲーム開発をするリポジトリに 1.で作ったgitリポジトリをサブツリーとして取り込む という感じになります。
    前提として、Unityプロジェクトをgitで管理することとなります。

git subtree 使い始めたらどうなった?

個人の感想ですが、

  • スクリプトコンポーネントのブラッシュアップがしやすくなった
  • ゲーム開発スピードが上がった(気がする)
  • バグの修正を反映するのが楽になった

という感じです。


実際にgit subtreeを使ってみる

コマンドラインとSourceTreeを用いた方法を紹介していきたいと思います。

1. スクリプトコンポーネントを一元管理するgitリポジトリを用意する


「このスクリプト、他のゲーム開発でも使いたい!!」


まずは、一元管理したいスクリプトコンポーネントを管理するUnityプロジェクトとgitリポジトリを用意します。
ポイントはUnityのプロジェクトをまるごとgit管理するのではなく、Assetsフォルダ以下のみをgit管理しましょう
f:id:takashicompany:20141210001013p:plain
Assetsフォルダ以下を管理する理由としては、ProjectSettingsなどは他のUnityプロジェクトでは不要なためです。

サンプルとしてソースコードをコミットしてプッシュしておきます。 f:id:takashicompany:20141210001238p:plain

2.ゲーム開発用のUnityプロジェクトのリポジトリにサブツリーとして一元管理リポジトリを追加する


「新しく作るゲームに、前に作ったゲームの機能を取り込みたい!!」
「ゲームを作りながらオレオレコンポーネントを整備していきたい!!」


ゲーム開発リポジトリにサブツリーを追加したいと思います。
f:id:takashicompany:20141210001300p:plain

  1. リモートの追加:
    git remote add [リモートリポジトリ名] [リモートリポジトリのパス]

  2. リモートをfetch:
    git fetch [リモートリポジトリ名]

  3. サブツリーの追加:
    git subtree add --prefix=[サブツリーを配置するパス] [リモートリポジトリ名] [サブツリーのブランチ名]

サンプルはこんな感じです。

git remote add subtree-assets git@github.com:takashicompany/unity-subtree-sample-subtree-assets.git

git fetch subtree-assets

git subtree add --prefix=Assets/Subtree subtree-assets master

サブツリーの追加が完了すると、ゲーム開発プロジェクト内にサブツリーのソースやコンポーネントが追加される。
f:id:takashicompany:20141210002238p:plain

SourceTreeでサブツリーを追加する場合は

  1. 画面左メニューから[サブツリー > サブツリーを追加/リンク]を選択
    f:id:takashicompany:20141210002006p:plain

  2. サブツリーのURLを入力、ブランチを選択し、ローカルパス(サブツリーの配置先)を設定する
    f:id:takashicompany:20141210002027p:plain
    ローカルパスは、Assetsからのパスを書くようにする

  3. ゲーム開発プロジェクトにサブツリーが追加される f:id:takashicompany:20141210002110p:plain
    コミットログもサブツリーの履歴が追加される
    f:id:takashicompany:20141210002127p:plain

3. ゲーム開発Unityプロジェクトからサブツリーリポジトリに変更を加える


「新しく作ったスクリプトを他プロジェクトでも使えるようにしたい!!」
コンポーネントのバグ直したから他のプロジェクトにも反映したい!!」


ゲーム開発プロジェクトでサブツリー内のスクリプトやPrefabに変更を加えたら
git subtree pushを実行してサブツリーのリポジトリに変更を反映します。

  1. 変更を加えたらいつもと同じくgit commitを実行
    f:id:takashicompany:20141210002502p:plain

  2. サブツリーに変更をpushをする
    git subtree push --prefix=[サブツリーのローカルパス] [リモートリポジトリ名] [サブツリーのブランチ名] を実行する。
     
    SourceTreeでsubtree pushをする際は、画面左側のサブツリー > サブツリーをプッシュを実行する。
    f:id:takashicompany:20141210002711p:plain
     
    プッシュが成功するとサブツリーのリポジトリにゲーム開発プロジェクトでの変更が取り込まれる。
    f:id:takashicompany:20141210002759p:plain

4.サブツリーの変更をゲーム開発リポジトリに取り込む


「サブツリー上でバグを直したので、ゲーム開発プロジェクトにも反映したい!!」
「他のゲーム開発プロジェクトで修正した変更をこのプロジェクトにも取り込みたい!!」


例としてサブツリーリポジトリにPrefabを追加して
git commitgit pushを実行します。
f:id:takashicompany:20141210003248p:plain

サブツリーリポジトリのコミットログも反映されているのを確認。
f:id:takashicompany:20141210003309p:plain

  1. サブツリーの変更をプルする
    git subtree pull --prefix=[サブツリーのローカルパス] [リモートリポジトリ名] [サブツリーのブランチ名]
    を実行する。
     
    SourceTreeでサブツリーの変更をプルする場合は、画面左側のサブツリー > サブツリーをプルを実行する。
    f:id:takashicompany:20141210003329p:plain
     
    サブツリーで変更した履歴がゲーム開発プロジェクトにも反映されている f:id:takashicompany:20141210003405p:plain
     
    ゲーム開発プロジェクトのサブツリーパス内にPrefabが入ってきている
    f:id:takashicompany:20141210003511p:plain

気をつけるポイントなど

  • サブツリー内の.metaファイルの更新は慎重に
    • 迂闊に.metaファイルを更新してしまうと、サブツリーを使用しているゲーム開発リポジトリで正しく動作しなくなるので。
  • 一つのサブツリーリポジトリ複数のゲーム開発リポジトリで利用する場合は、互換性に気をつける
    • クラス名や関数名、変数名、引数、アクセス修飾子など
  • サブツリーリポジトリのGameObjectにTagやLayerは設定しない
    • TagやLayerの情報はProjectSettingsに保持されるので、サブツリー側では設定しない方が安全かと
  • サブツリー内リポジトリスクリプトにはなるべくnamespaceを設定する

git submodule(サブモジュール) について

git subtreeと類似の機能として git submodule が挙げられます。
ざっくりgit submoduleについて説明すると、「gitリポジトリ以下に別のgitリポジトリの参照をつくる」というものです。
見た目的にはどちらもほとんど同じです。
git subtreeはgitリポジトリ内にサブツリーリポジトリをcloneする意味合いが強いですが、git submoduleは参照をするだけ(開発リポジトリから変更を加えないことが前提)という感じです。
(submoduleとsubtreeの比較もこちらに記載されております。)

個人的には

という感じで使い分けると良いかなと思います。
(まだgit submoduleをゴリゴリ使い倒していないので憶測ですが)

git subtreeでオレオレコンポーネントをガンガン作って、面白いゲームをドンドンリリースするぞーっ!!