【Unity】コードストリッピングを有効にしてリフレクションを使うとエラーになる件とその対処方法

コードストリッピングを有効にしてリフレクションを使うとエラーになる件とその対処方法についてまとめました。

Unity2018.3.6

コードストリッピング?

コードストリッピングとは使っていないメソッドやクラスをビルドに含めないようにしてバイナリのサイズを削減するための機能です。
UnityではPlayer Settingsでコードストリッピングを行うかどうかの設定ができます。

IL2CPPでビルドするか否かで微妙に設定項目が異なります。
このあたりはマニュアルを参照してください。

docs.unity3d.com

docs.unity3d.com

また下記の記事によると、コードストリッピングをすることでバイナリサイズはそれなりに変わるようです。

qiita.com

リフレクションと一緒に使うと必要なものまでストリッピングされる

このコードストリッピングを使う場合、リフレクションとの併用に気を付けなければなりません。

リフレクションを使って文字列でクラスやメソッドにアクセスしている場合、
そのクラスやメソッドが使われていないものと勘違いされてストリッピングされてしまう恐れがあるためです。

この挙動を確認するために次のようなコードを実行してみます。

using System;
using UnityEngine;

public class ExampleBehaviour : MonoBehaviour
{
    private void Start()
    {
        var instance = Activator.CreateInstance(Type.GetType("Example"));
        Debug.Log(instance);
    }
}

public class Example
{
}

Sctipting BackendはMono、Managed Stripping LevelはDisabledにしてビルドすると、これは正常に動きます。
ここで、Managed Stripping LevelをHighにしてみます。

f:id:halya_11:20190319220148p:plain

ストリッピングにより例外が発生しました。

f:id:halya_11:20190319220417p:plain

link.xml

コードストリッピングを無効にして済めば問題は起こらないのですが、
どうしてもコードストリッピングとリフレクションを併用したい場合にはlink.xmlを書くとストリッピングを明示的に防げます。

docs.unity3d.com

今回のExampleクラスについてもこれを記述してみます。

<linker>
  <assembly fullname="Assembly-CSharp">
      <type fullname="Example" preserve="all"/>
  </assembly>
</linker>

これでビルドを行うと、先ほどの例外が消えることが確認できました。

参考

docs.unity3d.com

docs.unity3d.com

qiita.com