Slide 1

Slide 1 text

【Unity】リリース時にデバッグ 用リソースをちゃんと消す方法 株式会社サイバーエージェント SGEコア技術本部 2022.10.21 矢野 春樹

Slide 2

Slide 2 text

はじめに 01

Slide 3

Slide 3 text

はじめに リリースビルドからはデバッグ用の諸々を綺麗に確実に削除しようというお話 ● ソースコード - e.g. チートコマンド ● アセット - e.g. デバッグ用のResourcesフォルダ ● シーン上のオブジェクト - e.g. SRDebuggerのPrefabインスタンス そのために使うべきUnityの機能をまとめます。

Slide 4

Slide 4 text

目次 1. はじめに 2. 必要な機能を把握する 3. ビルド前の準備 4. ビルドフロー

Slide 5

Slide 5 text

必要な機能を把握する 02

Slide 6

Slide 6 text

IPreprocessBuildWithReport ● プレイヤービルドの前処理を記述できる ● 同様に後処理を記述する IPostprocessBuildWithReport もある using UnityEditor.Build; using UnityEditor.Build.Reporting; public sealed class PreprocessBuild : IPreprocessBuildWithReport { public int callbackOrder => 0; public void OnPreprocessBuild (BuildReport report) { // ビルド前の処理を書く } }

Slide 7

Slide 7 text

IProcessSceneWithReport ● シーンをビルドしたりアセバン化したりエディタで再生する時に処理を加えられる ● プレイヤービルド時には IPreprocessBuildWithReport よりも後に呼ばれる using UnityEditor; using UnityEditor.Build; using UnityEditor.Build.Reporting; using UnityEngine.SceneManagement ; public sealed class ProcessScene : IProcessSceneWithReport { public int callbackOrder => 0; public void OnProcessScene (Scene scene, BuildReport report) { // エディタで再生した時には実行しない if (EditorApplication .isPlaying) return; // シーン上のオブジェクトを削除したりできる } }

Slide 8

Slide 8 text

#if 〜 #endif ● よくあるやつ ● コードを条件に応じてコンパイルする/しない ● Scripting Define Symbols などで定義されているシンボルに応じてコンパイルされる かが決まる #if DEVELOPMENT_BUILD // DevelopmentBuildがOnの時の処理 #else // DevelopmentBuildがOffの時の処理 #endif

Slide 9

Slide 9 text

Define Constraints ● asmdef に定義できる ● これが全て満たされている時のみアセンブリがコンパイルされる ● アセンブリ内の全てのコードを #if 〜 #endif で囲ってるイメージ

Slide 10

Slide 10 text

Conditionalアトリビュート ● 特定シンボルが有効じゃない時にメソッドの呼び出しをコンパイルしない ● 戻り値がないメソッドにのみ使える [Conditional("FOO_ENABLED")] private void Example() { // ここに書いた処理は、 FOO_ENABLED が定義されている時だけ実行される }

Slide 11

Slide 11 text

ビルド前にやっておくこと 03

Slide 12

Slide 12 text

デバッグ用モジュールのコンパイル条件を設定 ● デバッグ用モジュール = FPS表示機能、デバッグメニューなど ● アセンブリ化している場合には Define Constraints を使う ● してない場合は #if 〜 #endif で ● ビルド前にスクリプトごと削除(移動)してもOK

Slide 13

Slide 13 text

デバッグ用モジュールを参照しているコードにも設定 ● #if 〜 #endif で ● Conditional という手もある ● ビルド前にスクリプトごと削除(移動)してもOK private void Example() { #if DEBUG_ENABLED FPSCounter.Instance.Setup(); #endif }

Slide 14

Slide 14 text

ビルドフロー 04

Slide 15

Slide 15 text

1. デバッグ系のスクリプトを削除・無効化 ● IPreprocessBuildWithReport を使う ● 物理削除する場合 ○ 正確には削除ではなく移動し、IPostprocessBuildWithReport で戻す ○ もちろんmetaファイルも一緒に ● #if 〜 #endif や asmdef の Define Constraints などを使う場合 ○ Scripting Define Symbols を追加・削除する ○ PlayerSettings.SetScriptingDefineSymbolsForGroup() ● 依存関係を意識して処理順を設定しないとビルドエラー(コンパイルエラー)になる ので注意 ○ IPreprocessBuildWithReport.callbackOrder で処理順を指定できる ○ 数値が小さいほど早い段階で処理される

Slide 16

Slide 16 text

2. Resourcesなどのリソースを削除 ● 消さないとアプリに含まれちゃう系のものを削除 ○ ResourcesフォルダとかStreamingAssetsとか ● IPreprocessBuildWithReport を使う ○ 正確には削除ではなく移動し、IPostprocessBuildWithReport で戻す ○ もちろんmetaファイルも一緒に

Slide 17

Slide 17 text

3. シーン上のオブジェクトを削除 ● IProcessSceneWithReport を使う ○ GameObject名やコンポーネント名で判定して消したり ○ Debug タグをつけておいてタグで判定して消したり ○ その辺りは自由に ● プロジェクトのシーンアセットに変更は加わらない ○ 普通に Object.DestroyImmediate で削除すればOK

Slide 18

Slide 18 text

余談 05

Slide 19

Slide 19 text

ライブラリがあったらいいよね ● 指定したリソースをビルド前に移動、ビルド後に戻す ● 指定した Scripting Define Symbols を有効化・無効化する ● 処理順を指定できる ○ コンパイルエラーにならないように ● 指定したシーン上のオブジェクトを削除 ○ 指定方法はGameObject名とかタグ名とか選べる ● いくつかプロファイルを持てる ○ デバッグ用、リリース用、その他諸々の環境用・・ ● 使いやすいGUIでいい感じに設定できる(重要) ○ 保守性 ○ GUI 作らないならライブラリにするほどの話でもない ■ Undo/Redo、ドラッグで並び替え、スクリプトからも全ての操作が可能、etc..

Slide 20

Slide 20 text

ありがとうございました