アバターの改変作業を続けていると、「あの変更前に戻したい」「どこで壊したかわからない」という場面に必ずぶつかります。この記事では、VRChatのUnityプロジェクトをGitでバージョン管理する方法を、Git未経験者向けに解説します。GitHubへのアップロードなどオンライン操作は扱わず、ローカルでの履歴管理に絞って説明します。
Gitとは何か
Gitはファイルの変更履歴を記録するツールです。「セーブデータの管理システム」と思うと理解しやすいです。作業の節目ごとにスナップショット(コミット)を残しておけば、過去の任意の状態にいつでも戻せます。
Unityプロジェクトは特に壊れやすく、何かをいじった後に動かなくなるケースが多いです。Gitを使うと、壊れる前の状態を取り出せるので、安心して改変作業を進められます。
Gitのインストール
まだGitをインストールしていない場合は、Git for Windowsからインストーラーをダウンロードして実行してください。インストールが完了したら、Git Bashを開いて次のコマンドを実行します。
git --version
バージョン番号が表示されれば、インストール成功です。
リポジトリを作る
Gitでは、管理対象のフォルダのことを「リポジトリ」と呼びます。Unityプロジェクトのフォルダをリポジトリにするには、そのフォルダに移動してから git init コマンドを実行します。
cd C:\Users\yourname\UnityProjects\MyAvatar
git init
Initialized empty Git repository in ... と表示されれば成功です。これでフォルダ内に .git という隠しフォルダが作られ、ここに変更履歴が蓄積されていきます。
.gitignore を設定する
Unityプロジェクトには、Gitで管理する必要がないファイルが大量に含まれています。ビルドキャッシュや自動生成ファイルがその代表例です。これらを誤ってコミットしてしまうと、リポジトリが無駄に肥大化します。
.gitignore はGitが無視するファイルやフォルダを指定するための設定ファイルです。プロジェクトのルートフォルダに .gitignore というファイルを作成し、内容を書き込みます。
Unityプロジェクト向けの公式テンプレートが GitHub から公開されています。
このファイルの内容をそのままコピーして使うのが確実です。Library/ フォルダをはじめ、Unityが自動生成するキャッシュフォルダが網羅されています。Library/ をGitに含めてしまうと、リポジトリサイズが数GB単位で膨れ上がるため、必ず除外します。
Git LFS を設定する
Unityプロジェクトには .png、.fbx、.wav といったバイナリファイルが大量に存在します。Gitはバイナリファイルの扱いが苦手で、そのまま管理するとリポジトリがすぐに数十GBになります。
Git LFS(Large File Storage)はこの問題を解決します。バイナリファイルの本体をリポジトリの外部に移し、リポジトリ内にはその参照情報だけを保存する仕組みです。
Git LFS のインストール
git-lfs.com からインストーラーをダウンロードして実行します。インストール後、次のコマンドでGit LFSを有効化します。
git lfs install
Git LFS initialized. と表示されれば準備完了です。
.gitattributes でLFS管理対象を設定する
LFSで管理するファイルの種類は .gitattributes というファイルで指定します。プロジェクトルートに .gitattributes ファイルを作り、次の内容を書き込みます。
## Unity ##
# diff=csharp: C#の構造を理解した差分表示 / text: テキストファイルとして扱う
*.cs diff=csharp text
# text: テキストファイルとして扱う
*.cginc text
*.shader text
# merge=unityyamlmerge: UnityYAMLMergeでマージ / eol=lf: 改行コードをLFに統一
*.mat merge=unityyamlmerge eol=lf
*.anim merge=unityyamlmerge eol=lf
*.unity merge=unityyamlmerge eol=lf
*.prefab merge=unityyamlmerge eol=lf
*.physicsMaterial2D merge=unityyamlmerge eol=lf
*.physicMaterial merge=unityyamlmerge eol=lf
*.asset merge=unityyamlmerge eol=lf
*.meta merge=unityyamlmerge eol=lf
*.controller merge=unityyamlmerge eol=lf
*.overrideController merge=unityyamlmerge eol=lf
*.mask merge=unityyamlmerge eol=lf
## git-lfs ##
#Image
*.jpg filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.gif filter=lfs diff=lfs merge=lfs -text
*.psd filter=lfs diff=lfs merge=lfs -text
*.ai filter=lfs diff=lfs merge=lfs -text
*.hdr filter=lfs diff=lfs merge=lfs -text
*.tif filter=lfs diff=lfs merge=lfs -text
*.tiff filter=lfs diff=lfs merge=lfs -text
#Audio
*.mp3 filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text
*.ogg filter=lfs diff=lfs merge=lfs -text
#Video
*.mp4 filter=lfs diff=lfs merge=lfs -text
*.mov filter=lfs diff=lfs merge=lfs -text
#3D Object
*.FBX filter=lfs diff=lfs merge=lfs -text
*.fbx filter=lfs diff=lfs merge=lfs -text
*.blend filter=lfs diff=lfs merge=lfs -text
*.obj filter=lfs diff=lfs merge=lfs -text
#ETC
*.a filter=lfs diff=lfs merge=lfs -text
*.exr filter=lfs diff=lfs merge=lfs -text
*.tga filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.dll filter=lfs diff=lfs merge=lfs -text
*.unitypackage filter=lfs diff=lfs merge=lfs -text
*.aif filter=lfs diff=lfs merge=lfs -text
*.ttf filter=lfs diff=lfs merge=lfs -text
*.otf filter=lfs diff=lfs merge=lfs -text
*.rns filter=lfs diff=lfs merge=lfs -text
*.reason filter=lfs diff=lfs merge=lfs -text
*.lxo filter=lfs diff=lfs merge=lfs -text
設定は2つのブロックに分かれています。
Unity ブロック(## Unity ##)は、.mat や .prefab などUnityが生成するYAMLテキストファイルを対象にしています。merge=unityyamlmerge はUnityが提供するスマートマージツールを使う指定で、Gitが苦手なUnity独自フォーマットのマージを適切に処理します。eol=lf は改行コードをLFに統一する設定です。
git-lfs ブロック(## git-lfs ##)は、画像・音声・3DモデルなどのバイナリファイルをLFS管理にする設定です。各行の末尾の記述の意味は次の通りです。
| 記述 | 意味 |
|---|---|
filter=lfs |
このファイルをLFSで管理する |
diff=lfs |
差分表示もLFS経由で行う |
merge=lfs |
マージ処理もLFS経由で行う |
-text |
バイナリファイルとして扱い、改行コードを変換しない |
最初のコミットをする
.gitignore と .gitattributes の準備が整ったら、プロジェクトをGitに登録します。
まず、どのファイルがGitに認識されているかを確認します。
git status
「Untracked files」の一覧にプロジェクトのフォルダが表示されているはずです。Library/ などが表示されていなければ、.gitignore が正しく効いています。
次に、管理したいファイルをすべてステージングエリアに追加します。
git add .
. はカレントフォルダ以下のすべてのファイルを意味します。最後にコミットを実行します。
git commit -m "初回コミット: プロジェクトを追加"
-m の後ろのテキストはコミットメッセージです。何をしたかをひと言で書いておくと、後から履歴を見たときに便利です。
日常的な使い方
初期設定が終わったら、あとは作業の節目ごとにコミットを繰り返すだけです。作業を一段落させたら git status で変更ファイルを確認し、git add . でステージングして git commit -m "メッセージ" でコミットします。コミットのタイミングは「機能を一つ追加したとき」「うまくいったとき」など、区切りのいいところで行うとよいです。
過去のコミット一覧を見るには次のコマンドを使います。
git log --oneline
a3f1c2e シェイプキーの調整
d94b011 衣装のテクスチャを差し替え
b7e8a30 初回コミット: プロジェクトを追加
このような形でコミット履歴が表示されます。特定の状態に戻したい場合は、コミットハッシュ(先頭の7文字)を使って操作します。
過去の状態に戻す
コミット履歴を使って過去の状態に戻す方法は2種類あります。「とりあえず確認したい」場合と「完全に巻き戻したい」場合で使い分けます。
なお、コミットしていない変更が残っている場合はどちらの操作も失敗することがあります。その際は変更の退避(stash)を参照してください。
一時的に確認する(checkout)
「あのコミット時点でどうなっていたか見たい」だけなら git checkout を使います。
git checkout a3f1c2e
このコマンドを実行すると、リポジトリがそのコミット時点の状態になります。
ファイルを確認したら、次のコマンドで元に戻せます。
git checkout -
履歴は一切変わらないため、「壊れていない状態のテクスチャだけ取り出したい」といった用途に向いています。特定のファイルだけを過去の状態に戻すこともできます。
git checkout a3f1c2e -- Assets/Textures/face.png
永続的に巻き戻す(reset)
「このコミット以降の変更をすべて捨てて完全に戻したい」場合は git reset --hard を使います。
git reset --hard a3f1c2e
指定したコミット以降のコミットは履歴から削除され、ファイルもその時点の状態に戻ります。この操作は取り消せません。 実行する前に、本当に捨ててよい変更かどうかを git log --oneline で確認してから行うのが無難です。
変更を退避する(stash)
git checkout や git reset --hard を実行する前にコミットしていない変更が残っていると、競合が起きてエラーになることがあります。git stash -u で変更を一時退避することで回避できます。-u オプションを付けることで、まだGitに追加していない新規ファイル(未追跡ファイル)も含めて退避できます。
git stash -u # 変更を退避
git checkout a3f1c2e # または git reset --hard a3f1c2e
操作が終わったら git stash pop で退避した変更を元に戻せます。
git checkout - # checkoutの場合は元のコミットに戻る
git stash pop # 退避した変更を復元
GUIツールを使う
コマンド操作が難しければ、GUIツールを導入すると作業しやすくなります。コミット履歴をグラフで確認したり、変更差分をファイル単位で視覚的に確認したりできます。
Sourcetree は無料で使えるGitクライアントで、Windows・Macに対応しています。コミット・stash・checkoutといった操作をボタンで行えるため、コマンドを覚える前の入門としても使いやすいです。
まとめ
一度設定してしまえば、あとは git add . と git commit -m "..." を繰り返すだけです。「壊す前に戻せる」安心感があると、改変の試行錯誤が格段にしやすくなります。ぜひ日常の作業フローに取り入れてみてください。