概要

ドリコムのあるプロジェクトではUnity 2017を利用していましたが、Unity 2017がEOLを迎えるためUnity 2018へ移行中です。
この記事は、Unity 2018で実機ビルドに至るまでに起きた問題の事象と解決をまとめたものです。

移行するバージョンは2018.4.17f1です。
当初、移行先のバージョンは2018.4.14f1でしたが、対応中に何度か重要なリリースがあったため、都度バージョンアップのターゲットを挙げています。

エディタビルド

DLL名前競合解決

DLLの名前で競合が起こっていた問題を解決しました。
同名のDLLが複数あると怒られます。

PrecompiledAssemblyException:>PrecompiledAssemblyException:>PrecompiledAssemblyException: Multiple precompiled assemblies with the same name ICSharpCode.SharpZipLib.dll included for the current platform. Only one assembly with the same name is allowed per platform. Assembly paths: Assets/SmartLocalization/Scripts/Editor/ThirdParty/NPOI/ICSharpCode.SharpZipLib.dll, Assets/DrecomLib/Plugins/SharpZipLib/ICSharpCode.SharpZipLib.dll

対象はUnity Asset Store で頒布されている SmartLocalizationというアセットと、社内ライブラリであるDrecomLib(便宜上の名称)に含まれるSharpZipLib.dllでしたが、差分がなかったため片方を削除して解決しました。

find . -name ICSharpCode.SharpZipLib.dll | xargs md5
MD5 (./DrecomGameProject/Assets/SmartLocalization/Scripts/Editor/ThirdParty/NPOI/ICSharpCode.SharpZipLib.dll) = c8164876b6f66616d68387443621510c
MD5 (./DrecomGameProject/Assets/DrecomLib/Plugins/SharpZipLib/ICSharpCode.SharpZipLib.dll) = c8164876b6f66616d68387443621510c

新パーティクルシステムへの移行

旧パーティクルシステムがついに廃止されました。
そのため新システムへ移行しなければなりませんでした。

Assets/IGSoft_Resources/Scripts/NcEffect/NcParticleSystem.cs(68,12): error CS0246: The type or namespace name `ParticleEmitter' could not be found. Are you missing an assembly reference?

GameObject

GameObjectのコンポーネントを新パーティクルシステムへ置き換えるスクリプトが以下に公開されています。
旧パーティクルシステムが残っている2018.2以前で実行する必要がありました。
https://forum.unity.com/threads/legacy-particle-system-updater.510879/

まずは旧パーティクルシステムへの参照を洗い出す必要がありますが、対象のコンポーネントは以下のドキュメントを元に確認できます。
https://docs.unity3d.com/2018.4/Documentation/Manual/comp-ParticlesLegacy.html

find . -name '*.unity' -o -name '*.prefab' | xargs egrep "(EllipsoidParticleEmitter|MeshParticleEmitter|ParticleAnimator|ParticleRenderer|WorldParticleCollider)" > .legacy_particle_refs
egrep -oh "^[^:]+" .legacy_particle_refs | sort | uniq
./DrecomGameProject/Assets/AssetResources/AssetBundle/Resources/effects/shot/eff_adress_leaf_01/prefab/eff_adress_leaf_01.prefab
./DrecomGameProject/Assets/AssetResources/AssetBundle/Resources/effects/shot/eff_adress_leaf_02/prefab/eff_adress_leaf_02.prefab
./DrecomGameProject/Assets/AssetResources/AssetBundle/Resources/effects/shot/eff_ballhit_gacha/prefab/eff_ballhit_gacha.prefab
...

置き換えスクリプトはシーン単位での実行となります。
対象のprefabを適当なシーンに配置後、以下の手順で実行します。

  1. Assets>Upgrade Legacy Particlesを開く。
  2. Cleanup ModeはDelete Legacy Componentsに変更。
  3. Upgrade Everythingを実行。

スクリプト

今回、バージョンアップしたプロジェクトではパーティクルにFXMakerというアセットを使用しています。
FXMakerは旧システムと新システムに対応しているためコンパイルエラーが起こります。
残念ながらFXMakerはすでに開発を中止しているため、決別するかパッチを当てるかのいずれかの選択が必要です。
今回は移行コストとエンバグリスクを考慮し、パッチを当てました。
差分が大きいため全体はgistを参照してください。

https://gist.github.com/drecom-sgt/05748e6c4cb9c18495c5f8436eb9a9ae

link.xml

AssetBundleのみが参照するコードのストリッピングを回避するため、link.xmlに旧システムのクラスがリストされています。これも削除しました。

--- a/DrecomGameProject/Assets/link.xml
+++ b/DrecomGameProject/Assets/link.xml
@@ -1,8 +1,4 @@
<linker>
   <assembly fullname="UnityEngine">
-    <type fullname="UnityEngine.ParticleEmitter" preserve="all"></type>
-    <type fullname="UnityEngine.EllipsoidParticleEmitter" preserve="all"></type>
-    <type fullname="UnityEngine.ParticleAnimator" preserve="all"></type>
-    <type fullname="UnityEngine.ParticleRenderer" preserve="all"></type>
   </assembly>
 </linker>

RuntimeAnimatrorControllerの直接生成回避

RuntimeAnimatorControllerのコンストラクタがpublicでなくなり直接生成できなくなりました。

Assets/Scripts/Common/CharacterModel/CharacterAnimationLoader.cs(241,52): error CS1540: Cannot access protected member `UnityEngine.RuntimeAnimatorController.RuntimeAnimatorController()' via a qualifier of type `UnityEngine.RuntimeAnimatorController'. The qualifier must be of type `DrecomGameProject.CharacterAnimationLoader' or derived from it

今回のプロジェクトではnullオブジェクトとして生成しているのみだったのでnullを返して回避しました。

AnimatorOverrideController createCtrl = new AnimatorOverrideController();
createCtrl.runtimeAnimatorController = new RuntimeAnimatorController();
return createCtrl;

旧ネットワークシステム置き換え

旧ネットワークシステムが廃止されたので新システムへ移行しなければなりませんでした。

Assets/Photon Unity Networking/Editor/PhotonNetwork/PhotonConverter.cs(387,49): error CS0619: `UnityEngine.NetworkView' is obsolete: `The legacy networking system has been removed in Unity 2018.2. Use Unity Multiplayer and NetworkIdentity instead.'

旧システムを使用しているのはPhoton Unity Networking(以下PUN)のみ。バージョンはv1.8とかなり古いものを利用していました。

egrep 'v[0-9.]+' DrecomGameProject/Assets/Photon\ Unity\ Networking/changelog.txt | head -n 1
v1.80 (15. December 2016)

PUNは現在v1系とv2系にわかれてメンテナンスされています。
v2系は大幅なAPI変更があるため、移行コストとリスクを考慮しv1系を維持することにしました。

PUN v1 https://assetstore.unity.com/packages/tools/network/photon-unity-networking-classic-free-1786
PUN v2 https://assetstore.unity.com/packages/tools/network/pun-2-free-119922

PUN v1の最新版v1.101へ移行。3年未来へ。

egrep 'v[0-9.]+' DrecomGameProject/Assets/Photon\ Unity\ Networking/changelog.txt | head -n 1
v1.101 (12. November 2019)

これにより PhotonNetwork.OnEventCallへのコールバック登録方法が変更されたことでエラーになりました。

Assets/Scripts/Round/DuelPhoton/NetworkController.cs(141,23): error CS0070: The event `PhotonNetwork.OnEventCall' can only appear on the left hand side of += or -= when used outside of the type `PhotonNetwork'

以下のように対応しています。

-            PhotonNetwork.OnEventCall = OnEvent;
+            PhotonNetwork.OnEventCall += OnEvent;

エディタランタイム

“Cannot set the parent of the GameObject”エラー

Destroy中に親を変更しようとして怒られていおり、2017でも挙動には変わっていません。2018からエラーを吐くようになったようです。
Destroy中はSetPraentしないように変更して解決しました。

iOSビルド

CODE_SIGN_ENTITLEMENTSエラー

CODE_SIGN_ENTITLEMENTSの値がおかしいと怒られる。

error: The file "/Users/drecomshare/.jenkins/workspace/PERSONAL_iOS/DrecomGameProject/XcodeProject/Develop.entitlements Unity-iPhone/Production.entitlements" could not be opened. Verify the value of the CODE_SIGN_ENTITLEMENTS build setting for target "Unity-iPhone" and build configuration "Release" is correct and that the file exists on disk. (in target 'Unity-iPhone')

CODE_SIGN_ENTITLEMENTSはEntitlementsPostProcess.OnPostProcessで追加しています。

proj.AddBuildProperty(target_guid, "CODE_SIGN_ENTITLEMENTS", target_name + "/" + file_name);

初期値(Develop.entitlements)が自動で入るようになり、その末尾にUnity-iPhone/Production.entitlementsを追加してしまっているようでした。
値を追加ではなく置き換えるように変更してもよいのですが、その際は Player Settings > iOS > Configuration > Automatically add capabilitiesとして自動追加の有無を切り替える設定がありました。無効化して解決しています。

iOSランタイム

iOS 9 非推奨 API 利用によるクラッシュ

Unity2018でiOS8以下が非対応となりDeployment TargetがiOS9に設定されるようになっていましたが、iOS 9 で deprecated になっていた下記のメソッドが実装されていたため発生していました。

- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options
{
    ...

    return NO;
}

参考: http://nlogic.jp/?p=439

Androidビルド

Unable to locate Android NDKエラー

Unity 2017で設定していたNDK(r13b)だと怒られます。

DisplayProgressbar: Detect Android NDK
UnityException: Android SDK not found
Unable to locate Android NDK.

2018.4ではNDK(r16b)が必要とのことでした。
https://docs.unity3d.com/Manual/android-sdksetup.html

r16b以下から落としたもので設定して解決しています。
https://dl.google.com/android/repository/android-ndk-r16b-darwin-x86_64.zip

Unknown CPU architectureエラー

iOSプラグインに対して、このアーキテクチャ知らないよと怒られています。

Exception: Unknown CPU architecture  for library Assets/DrecomLibSubmodules/SNS/Plugins/iOS/libSNS.a

プラットフォームがAnyになっていました。
Plugins/iOS/配下にあってもPlatform設定の優先度が上がったようです。iOSのみに変更して解決しました。

AssetBundleビルド

エディタのウィンドウを開こうとして怒られました。

63625 Unknown renderer!
63626 UnityEditor.GUIView:Internal_Init(Int32, Int32)

Unity 2017用のmetaファイルが残っていたのが原因でした。
ビルド時にUnity 2018用のmetaへの更新が入り、本来発火しないプロジェクトファイルの変更イベントが走ったことが原因です。
対象のmetaファイルをUnity 2018用に更新して解決しました。

About the Author

みんゴルチーム

mingol_team

永井 雅人

グリーのWright Flyer Studiosを経て、2018年8月にドリコム入社。
みんゴルのリードエンジニア兼クライアントエンジニア。
「パーフェクトJava」(技術評論社)共著。

----

onda

アーケード・家庭用・アプリと渡り歩いてきて現在クライアントエンジニア。
業務以外の時間は育児に全振りの毎日です。