[Unity] アップデートしてみて躓いたことを並べてみる

# はじめに
どうも〜〜ちぇるまる（@cherumaru）と申します。
ここ数年はUnityやらUnreal Engineやらを使って、3DゲームやVRアプリの開発をやっております。
最近業務でUnityを5.5→2017.1にアップデートしたので、過去のアップデート経験談を交え、個人的に躓いたところをピックアップして書いていこうと思います。

# 対象環境
Windows / MacOS
Unity
5.1 → 5.3
5.3 → 5.4 / 5.5 / 5.6
5.5 → 2017.1

# アップデートの前に
アップデート作業を行う前に、気をつけておきたいことを列記しておきます。
（何度もアップデートを行っている方には常識的な話かもしれませんが……）
## Unityは上書きインストールしない
新しいバージョンのUnityをクリーンインストールするため、そして万が一のアップデートの巻き戻しが発生することも考慮し、新しいバージョンで上書きインストールせず、常に別フォルダへインストールするようにします。
Editorのインストールフォルダを分けることで、Unityの複数バージョンを共存させられます。
インストール後にルートフォルダをリネームしても問題は起きないので、新しいバージョンをインストールする前に **古いバージョンのUnity Editorのルートフォルダをリネームしておく** ことをオススメします。
こうしておくと、手元の最新版は特にフォルダ指定をしなくても、同じフォルダにインストールされるので便利です。
### Unityはマイナーアップデートでも変更が大きい
たとえパッチ版であったとしても、アップデートがされるたびに、Unityは多くの更新がなされています。リリースノートを見ていただけると、更新の範囲が多岐にわたっていることをご理解いただけると思います。
いくらリリースノートを熟読していても、想定外の挙動変更やバグは多々あります。そのため、マイナーアップデートであったとしても、古いバージョンが共存している環境を作っておくほうが良い、と個人的には思っています。
## Asset や SDK の互換性・アップデート方法を確認しておく
Asset StoreのAssetや、サードパーティのSDKを利用しているのであれば、アップデートが必要か、アップデート予定のバージョンに対応しているのか、の事前調査は必須です。ここで確認・対応漏れがあると、アップデート後、Exceptionの嵐で苦労します、ホントに。
## バージョン管理システムを導入しておく
Subversion や git など、現在の開発現場では当たり前のように使われているバージョン管理システムですが、いまだに手動コピーでバックアップ管理しているプロジェクトも中にはあります（実際にありました……もちろん個人開発ではなく）。
アップデートのみならず、普段の開発効率も格段に上がりますので、いっその事この機会に導入してしまいましょう！
## 現状のプロジェクトのコピーをとっておく
バージョン管理されているものとは別に、万が一ファイルが破損した時のために、バックアップとして、個人のローカル環境にプロジェクトのコピーをとっておきましょう。一度新しいバージョンでプロジェクトを開くと **Project SettingsやLibraryにも直接変更が入ってしまうため** ~~時間がかかる＋容量が大きくなるのは承知の上で~~ プロジェクトフォルダを丸ごとバックアップしておくと良いでしょう。

# アップデート
## Unity Editorからプロジェクトを開く
新しいバージョンのUnity Editorを起動し、変換したいプロジェクトを選択するだけでコンバータが走って、自動変換が始まります。
途中、何度かダイアログが出ますが、迷わず「OK」ボタンを押して前へ進みましょう！
5.5？以降では古いUnity APIも新しい形式に自動で書き換えてくれます。自動書き換えなので、プログラムによっては誤変換が出ることもありますが、こちらは変換が終了してプロジェクトが開いた後、地道に直していくしか方法がありません。。。ですが、手動で書き直すより全然手間はかかりませんし、経験上2017シリーズで変換ミスはそうそう起こらない……気がします。
## Asset・SDKを更新する
コンバートが終了すると、プロジェクトが開きます。きっとConsoleは「:warning:」と赤い文字で埋め尽くされていることでしょう。。。
**エラーの修正より先に、Asset・SDKのアップデートを済ませます** 。これらに起因しているエラーがなくせます。
## ビルドエラー・Warningを直す
一旦ConsoleのClearボタンを押し、残ったExceptionから修正していきます。
大別すると以下のような感じです。
### Obsolete
Unity APIの他に、Mono側でObsoleteになっているメソッドを修正していきます。Consoleのエラーメッセージを元に、置換先メソッドに書き換えていきます。
Unity Editorのバージョンが上がると、同時に内部で使っているMono（≒C#）のバージョンが上がることもあります。5.5以降、正式に対応しているC#のバージョンに変更はありませんが（2017.2の時点でもC#6対応はexperimental扱い）、これより以前のバージョンからのアップデートの場合、プロジェクトにもよりますが対応が必要です。
#### Warning扱いのObsoleteも直そう
中にはExceptionではなく、Warning扱いになっているObsoleteのメソッドやクラスもあります。アプリやシステムがエラーで落ちることはないにしても、公式で推奨されていないことに変わりはありませんし、後々の手間も考えてできる限り修正していきましょう。
### using ディレクティブ欠損
* namespace自体が廃止の場合は、関連のクラス・メソッド・フィールドも NotFoundException となっています。  
代替のnamespaceをusingし、プログラム自体の修正をしていくが、最悪代替すら見つからない場合、アプリの設計から見直すこともありますが、こればかりはプロジェクト依存。
* 欠損部分が以下のように、Unityのバージョンに依存している場合、 **通常は #if〜#endifを削ります** 。

```csharp:example.cs
  #if UNITY_5_3
  using SceneManagement;
  #endif
```
　第三者に提供するモジュールなど、下位互換が必要な場合のみ、以下のようにアップデート予定のバージョンに対応するdefineに変更します。

```csharp:example_SDK.cs
  #if UNITY_5_3_OR_NEWER
  using SceneManagement;
  #endif
```
　（Asset や SDK の最新版ソースで出た場合は、速やかに開発元に修正を依頼しましょう）
### その他
* Prefab・Textureなどのバイナリファイルが破損している場合は、Editorのプロジェクトエクスプローラで右クリックし **RefreshとReImport** を試します。  
それでも直らない場合は、バックアップから該当ファイルをコピー、 **エクスプローラ（or Finder）で置換** 後、プロジェクトエクスプローラから再度Refresh・ReImportしましょう。
* 他、原因不明のExceptionの場合も、バックアップから該当ファイルを戻す→Unity Editor再起動で直る場合があります。

## テスト起動
ビルドエラーがなくなったら、Unity EditorからPlayを押してテスト起動させます。一通り触ってみてエラーも差異もなければ、ひとまずアップデート作業は完了です。お疲れ様でした。

# エラーにならないトラブル
Unityで昨今よく更新されている部分ではありますので、こちらも残しておきます。
## 3Dモデルの色合いがおかしくなる
昨今ShaderやLighting周りの更新もなされているため、よくあるトラブルのようです。以前、5.6以降のUnityへアップデートした際、モデルの色がすべて黒っぽくなってしまいました。。。
前もってbakeしているモデルは、再度焼き直すことで元に戻ります。
それでも色合いが戻らない場合は、モデル側で色調整をするなり、Shaderの修正をするなり、Post Processing Stackでごにょごにょするなり……するのですが、これはまた次の機会があれば。
# おわりに
Unityに限らず、どの言語でもどのフレームワークでも言えることなのですが、アップデート作業は、アップデート前のバージョンとプロジェクト依存の部分が非常に大きく、何度やっても試行錯誤の連続です。いくら下準備を行っていても、想定外のトラブルは毎度と言っていいほど起きますし、その度にExceptionと見えないエラーとの戦いです。
特に最近のプロジェクトは規模も大きくなり、システムひとつのアップデートであっても影響範囲が大きく、さらにアップデート作業を複雑なものにしています。頻繁に行うものではないため、普段の開発作業では考えを巡らせることのないアップデート作業ですが、ちょっとでも楽になれる方法を、普段から頭の片隅に置いて開発ができればなぁ……と思いました。

今回はUnityに絞って書かせていただきましたが、機会があればPHPでのアップデートについても書かせていただきたいです。