📘

UnityでProduction時に含めないコードをどうやって作るか

に公開

概要

いろんなパターンがあります。

全体の話としては以下のスライドを参照してください。

【Unity】リリース時にデバッグ用リソースをちゃんと消す方法
https://speakerdeck.com/harumak/unity-ririsushi-nitehatukuyong-risosuwotiyantoxiao-sufang-fa

覗き方

ビルドしたapkを7zipなどで解凍します。

assets\bin\Data\ScriptingAssemblies.json を開いて、適当な改行を加えると( https://jsonlint.com/ がこの用途にべんり!)

たとえばこんな感じで「あ、このプロジェクトはUniTask.dllを使ってる!」ってわかります。

Jsonの中身例(省略済み)
{
    "names": [
        "UnityEngine.dll",
        "UnityEngine.AIModule.dll",
        "UnityEngine.ARModule.dll",
        "UnityEngine.AccessibilityModule.dll",
        "UnityEngine.AndroidJNIModule.dll",
        "UnityEngine.AnimationModule.dll",
        "UnityEngine.AssetBundleModule.dll",
        "UnityEngine.AudioModule.dll",
        "UnityEngine.ClothModule.dll",
        "UnityEngine.ContentLoadModule.dll",
        "UnityEngine.WindModule.dll",
        "UnityEngine.XRModule.dll",
        "UniTask.TextMeshPro.dll",
        "UniTask.DOTween.dll",
        "UniTask.Addressables.dll",
        "Unity.VisualScripting.Core.dll",
        "UnityEngine.UI.dll",
        "UniTask.Linq.dll",
        "Unity.VisualScripting.Flow.dll",
        "Unity.Timeline.dll",
        "Project.Editor.dll",
        "Project.Runtime.dll",
        "Unity.TextMeshPro.dll",
        "UniTask.dll",
        "Unity.VisualScripting.State.dll",
        "Unity.VisualScripting.Antlr3.Runtime.dll"
    ],
    "types": [
        2,
      
        16,
        16
    ]
}

ほかにもRuntimeInitializeOnLoads.jsonを読むと同Attributeを付加したクラスやメソッド名がわかるので、<del>不正なアプリ書き換えのエントリーポイントの手がかりになるので注意!</del>ここでもUniTaskって文字が見えますね。

RuntimeInitializeOnLoads.jsonの中身例
{
    "root": [
        {
            "assemblyName": "UniTask",
            "nameSpace": "Cysharp.Threading.Tasks",
            "className": "PlayerLoopHelper",
            "methodName": "Init",
            "loadTypes": 2,
            "isUnityClass": false
        },
        {
            "assemblyName": "Unity.VisualScripting.Core",
            "nameSpace": "Unity.VisualScripting",
            "className": "RuntimeVSUsageUtility",
            "methodName": "RuntimeInitializeOnLoadBeforeSceneLoad",
            "loadTypes": 1,
            "isUnityClass": true
        }
    ]
}

よくあるのがManaged Stripping Levelの操作ですが、HighにしてもRuntimeで一切使っていないUniTaskのdllが含まれたままです。

実践編

外部ライブラリ編

たとえばUnityDebugSheetは便利ですが、出荷時に含められたらピンチ、どうやってるか見てみましょう。

たとえばOnPreProcessBuldでpackage.jsonの中身を物理的にjqなどで書き換えてしまう、というのが思いつきますが、OnPreProcessBuldのタイミングでは既にパッケージ解決は終わっているため不可能です。
https://discussions.unity.com/t/change-package-at-build-time/1503900/3

よって、外部からのビルドスクリプトで変更しつつBatchmodeで起動してビルド…でしょうか。
(Editorでだけ使っている、とかでコンパイルエラー起きそうで嫌ですね)

一番手軽なのはAssets以下に外部ライブラリのパッケージをコピーして、あなたのプロジェクトに合ったDefine Constraintsを設定することだと思います。

例:UniTaskをEditorでだけ使っている場合のDefine Constraints

たとえばUnityEditorでだけUniTaskを使っていて、出荷時コードに含めたくないとき。

↑にあるようにUniTaskパッケージをAssets以下にコピーしてRuntime以下のすべてのasmdefファイルにDefine ConstraintsでUNITY_EDITORを定義しておきましょう。

  • UniTask.asmdef
  • UniTask.Addressables.asmdef
  • UniTask.DOTween.asmdef
  • UniTask.TextMeshPro.asmdef
  • UniTask.Linq.asmdef

など、複数のasmdefがあることに注意してください。

ビルドにUniTask系のdllが含まれないことを確認しましょう。

内部コード編

asmdefのDefine Constraintsで対応可能です。
https://www.hanachiru-blog.com/entry/2022/11/25/120000
!ENABLE_DEBUG_FEATURE
など先頭にビックリマークをつけるとfalse時のみ含める、なども書けます。

UnityDebugSheetではこのようにライブラリ内部で既に定義済みなので、内部コード編と同様にDefine Constraintsで対応可能です。

https://github.com/Haruma-K/UnityDebugSheet/blob/2b1cf90f0375e10c9c0909cc91c5b92d707f2ce3/Assets/UnityDebugSheet/Runtime/UnityDebugSheet.asmdef#L14

Discussion