Zenn
📗

【Unity】DefineSymbolをスクリプトから追加する方法

2025/03/25に公開
3

はじめに

初めての方も、そうでない方もこんにちは!
現役ゲームプログラマーのたむぼーです。
自己紹介を載せているので、気になる方は見ていただければ嬉しいです!

今回は
 DefineSymbolをスクリプトから追加する方法
について紹介します

https://zenn.dev/tmb/articles/1072f8ea010299

DefineSymbolとは

Define Symbol(定義シンボル)は、Unityにおいて条件付きコンパイルを行うために使われる仕組みです。
特定のコードブロックを、ある条件(シンボルが定義されているかどうか)によって有効・無効にできるため、プラットフォームごとの処理切り替えや、開発/本番の環境分岐などに活用されます。

#if DEBUG_MODE
    Debug.Log("デバッグモードです");
#endif

上記のように DEBUG_MODE というシンボルが定義されている場合にだけ、Debug.Log のコードが有効になります。

主な用途

・開発中のみ表示したいログの制御
・有償版/無償版などのビルド差分の制御
・プラットフォーム別の機能制御(例:iOS専用コード)
・アセットやパッケージによる機能のON/OFF切り替え

設定方法

Unityの上部メニューから
Edetor > Project Settings > Player > Other Settings > Scripting Define Symbols

DefineSymbolをスクリプトから追加

使い方

Example.cs
public void Example()
{
    // 全てのプラットフォームに【DEBUG_MODE】を追加
    DefineSymbolsHelper.AddDefineSymbol(DefineSymbolsPlatform.All, "DEBUG_MODE");

    // Androidの設定から【DEBUG_MODE】を削除
    DefineSymbolsHelper.RemoveDefineSymbol(DefineSymbolsPlatform.Android, "DEBUG_MODE");
}

プラットフォームのEnumの定義

DefineSymbolsPlatform
DefineSymbolsPlatform.cs
#if UNITY_EDITOR
/// <summary>
/// プラットフォーム
/// </summary>
public enum DefineSymbolsPlatform
{
    Android,
    iOS,
    PC,
    All
}
#endif

ヘルパークラスの実装

DefineSymbolsHelper
DefineSymbolsHelper.cs
#if UNITY_EDITOR
using UnityEditor;

public static class DefineSymbolsHelper
{
    /// <summary>
    /// DefineSymbolを追加
    /// </summary>
    public static void AddDefineSymbol(DefineSymbolsPlatform platform, string symbol)
    {
        switch (platform)
        {
            case DefineSymbolsPlatform.Android:
                AddDefineSymbolGroup(BuildTargetGroup.Android, symbol);
                break;

            case DefineSymbolsPlatform.iOS:
                AddDefineSymbolGroup(BuildTargetGroup.iOS, symbol);
                break;

            case DefineSymbolsPlatform.PC:
                AddDefineSymbolGroup(BuildTargetGroup.Standalone, symbol);
                break;

            case DefineSymbolsPlatform.All:
                AddDefineSymbolGroup(BuildTargetGroup.Android, symbol);
                AddDefineSymbolGroup(BuildTargetGroup.iOS, symbol);
                AddDefineSymbolGroup(BuildTargetGroup.Standalone, symbol);
                break;
        }
    }

    /// <summary>
    /// DefineSymbolを削除
    /// </summary>
    public static void RemoveDefineSymbol(DefineSymbolsPlatform platform, string symbol)
    {
        switch (platform)
        {
            case DefineSymbolsPlatform.Android:
                RemoveDefineSymbolGroup(BuildTargetGroup.Android, symbol);
                break;

            case DefineSymbolsPlatform.iOS:
                RemoveDefineSymbolGroup(BuildTargetGroup.iOS, symbol);
                break;

            case DefineSymbolsPlatform.PC:
                RemoveDefineSymbolGroup(BuildTargetGroup.Standalone, symbol);
                break;

            case DefineSymbolsPlatform.All:
                RemoveDefineSymbolGroup(BuildTargetGroup.Android, symbol);
                RemoveDefineSymbolGroup(BuildTargetGroup.iOS, symbol);
                RemoveDefineSymbolGroup(BuildTargetGroup.Standalone, symbol);
                break;
        }
    }

    /// <summary>
    /// DefineSymbolが存在するか
    /// </summary>
    public static bool IsDefineSymbolPresent(DefineSymbolsPlatform platform, string symbol)
    {
        return platform switch
        {
            DefineSymbolsPlatform.Android => IsDefineSymbolPresent(BuildTargetGroup.Android, symbol),
            DefineSymbolsPlatform.iOS => IsDefineSymbolPresent(BuildTargetGroup.iOS, symbol),
            DefineSymbolsPlatform.PC => IsDefineSymbolPresent(BuildTargetGroup.Standalone, symbol),
            DefineSymbolsPlatform.All => IsDefineSymbolPresent(BuildTargetGroup.Android, symbol)
                                          && IsDefineSymbolPresent(BuildTargetGroup.iOS, symbol)
                                          && IsDefineSymbolPresent(BuildTargetGroup.Standalone, symbol),
            _ => false,
        };
    }

    /// <summary>
    /// DefineSymbolが既に存在するかを確認
    /// </summary>
    private static bool IsDefineSymbolPresent(BuildTargetGroup buildTargetGroup, string symbol)
    {
        string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup);
        return IsDefineSymbolPresent(defines, symbol);
    }

    /// <summary>
    /// DefineSymbolが既に存在するかを確認
    /// </summary>
    private static bool IsDefineSymbolPresent(string defines, string symbol)
    {
        return defines.Contains(symbol);
    }

    /// <summary>
    /// DefineSymbolをグループ毎に追加
    /// </summary>
    private static void AddDefineSymbolGroup(BuildTargetGroup buildTargetGroup, string symbol)
    {
        string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup);

        // DefineSymbolの存在チェック
        if (!IsDefineSymbolPresent(defines, symbol))
        {
            if (!string.IsNullOrEmpty(defines))
            {
                defines += ";";
            }
            defines += symbol;
            PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, defines);
            AssetDatabase.Refresh();
        }
    }

    /// <summary>
    /// DefineSymbolをグループ毎に削除
    /// </summary>
    private static void RemoveDefineSymbolGroup(BuildTargetGroup buildTargetGroup, string symbol)
    {
        string defines = PlayerSettings.GetScriptingDefineSymbolsForGroup(buildTargetGroup);

        // DefineSymbolの存在チェック
        if (IsDefineSymbolPresent(defines, symbol))
        {
            defines = defines.Replace(symbol, "").TrimEnd(';').TrimStart(';');
            PlayerSettings.SetScriptingDefineSymbolsForGroup(buildTargetGroup, defines);
            AssetDatabase.Refresh();
        }
    }
}
#endif

おまけ(拡張ウィンドウでの設定)

DefineSymbolsSetterWindow
DefineSymbolsSetterWindow.cs
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using System;
using System.Collections.Generic;

public class DefineSymbolsSetterWindow : EditorWindow
{
    private DefineSymbolsPlatform _selectedPlatform = DefineSymbolsPlatform.All;
    private string _defineSymbol = "";
    private Vector2 _scrollPos;

    /// <summary>
    /// ウィンドウを作成
    /// </summary>
    [MenuItem("Tools/DefineSymbolsSetter")]
    public static void ShowWindow()
    {
        var window = GetWindow<DefineSymbolsSetterWindow>("Define Symbols Setter");
        window.minSize = new Vector2(500, 300);
    }

    /// <summary>
    /// 更新
    /// </summary>
    private void OnGUI()
    {
        EditorGUILayout.LabelField("Define Symbol 設定", EditorStyles.boldLabel);
        EditorGUILayout.Space();

        _selectedPlatform = (DefineSymbolsPlatform)EditorGUILayout.EnumPopup("対象プラットフォーム", _selectedPlatform);
        _defineSymbol = EditorGUILayout.TextField("Define Symbol", _defineSymbol);

        EditorGUILayout.BeginHorizontal();
        if (GUILayout.Button("Add"))
        {
            if (!string.IsNullOrEmpty(_defineSymbol))
            {
                DefineSymbolsHelper.AddDefineSymbol(_selectedPlatform, _defineSymbol);
                CustomLogger.Info("Define Symbols Setter", ColorPallet.Aqua, $"Symbol '{_defineSymbol}' を {_selectedPlatform} に追加しました。");
                ShowNotification(new GUIContent($"Symbol '{_defineSymbol}' を {_selectedPlatform} に追加しました。"));
            }
            else
            {
                EditorUtility.DisplayDialog("エラー", "Define Symbol を入力してください。", "OK");
            }
        }

        if (GUILayout.Button("Remove"))
        {
            if (!string.IsNullOrEmpty(_defineSymbol))
            {
                DefineSymbolsHelper.RemoveDefineSymbol(_selectedPlatform, _defineSymbol);
                CustomLogger.Info("Define Symbols Setter", ColorPallet.Aqua, $"Symbol '{_defineSymbol}' を {_selectedPlatform} から削除しました");
                ShowNotification(new GUIContent($"Symbol '{_defineSymbol}' を {_selectedPlatform} から削除しました。"));
            }
            else
            {
                EditorUtility.DisplayDialog("エラー", "Define Symbol を入力してください。", "OK");
            }
        }
        EditorGUILayout.EndHorizontal();

        EditorGUILayout.Space(15);
        EditorGUILayout.LabelField("現在の Define Symbols", EditorStyles.boldLabel);

        _scrollPos = EditorGUILayout.BeginScrollView(_scrollPos);

        if (_selectedPlatform == DefineSymbolsPlatform.All)
        {
            DrawSymbolsForAllPlatforms();
        }
        else
        {
            var group = PlatformToBuildTargetGroup(_selectedPlatform);
            DrawSymbolsForPlatform(group, _selectedPlatform.ToString());
        }

        EditorGUILayout.EndScrollView();
    }

    /// <summary>
    /// 指定プラットフォームのDefineSymbolsを表示
    /// </summary>
    private void DrawSymbolsForPlatform(BuildTargetGroup group, string label)
    {
        string symbols = PlayerSettings.GetScriptingDefineSymbolsForGroup(group);
        string[] defines = symbols.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

        EditorGUILayout.LabelField($"--- {label} ---", EditorStyles.boldLabel);

        if (defines.Length == 0)
        {
            EditorGUILayout.LabelField("(シンボルなし)");
        }
        else
        {
            foreach (var symbol in defines)
            {
                DrawSymbolRow(symbol);
            }
        }

        EditorGUILayout.Space(10);
    }

    /// <summary>
    /// 全プラットフォームのDefineSymbolsを表示
    /// </summary>
    private void DrawSymbolsForAllPlatforms()
    {
        var android = new HashSet<string>(PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Android).Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries));
        var ios = new HashSet<string>(PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.iOS).Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries));
        var pc = new HashSet<string>(PlayerSettings.GetScriptingDefineSymbolsForGroup(BuildTargetGroup.Standalone).Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries));

        var common = new HashSet<string>(android);
        common.IntersectWith(ios);
        common.IntersectWith(pc);

        var androidOnly = new HashSet<string>(android);
        androidOnly.ExceptWith(common);

        var iosOnly = new HashSet<string>(ios);
        iosOnly.ExceptWith(common);

        var pcOnly = new HashSet<string>(pc);
        pcOnly.ExceptWith(common);

        // 共通シンボル
        EditorGUILayout.LabelField("=== 共通シンボル(全プラットフォーム) ===", EditorStyles.boldLabel);
        if (common.Count == 0)
        {
            EditorGUILayout.LabelField("(共通シンボルなし)");
        }
        else
        {
            foreach (var symbol in common)
            {
                DrawSymbolRow(symbol);
            }
        }

        // 各プラットフォーム専用シンボル
        DrawPlatformSymbols("Android 専用", androidOnly);
        DrawPlatformSymbols("iOS 専用", iosOnly);
        DrawPlatformSymbols("PC 専用", pcOnly);
    }

    /// <summary>
    /// 指定プラットフォームのDefineSymbolsを表示
    /// </summary>
    private void DrawPlatformSymbols(string label, HashSet<string> symbols)
    {
        EditorGUILayout.Space();
        EditorGUILayout.LabelField($"=== {label} ===", EditorStyles.boldLabel);

        if (symbols.Count == 0)
        {
            EditorGUILayout.LabelField("(シンボルなし)");
        }
        else
        {
            foreach (var symbol in symbols)
            {
                DrawSymbolRow(symbol);
            }
        }
    }

    /// <summary>
    /// 1つのDefineSymbolを行として表示
    /// </summary>
    private void DrawSymbolRow(string symbol)
    {
        EditorGUILayout.BeginHorizontal();
        EditorGUILayout.LabelField($"- {symbol}", GUILayout.MaxWidth(position.width - 60));
        if (GUILayout.Button("Copy", GUILayout.Width(40)))
        {
            EditorGUIUtility.systemCopyBuffer = symbol;
            CustomLogger.Info("Define Symbols Setter", ColorPallet.Aqua, $"Symbol '{symbol}' をコピーしました");
            ShowNotification(new GUIContent($"'{symbol}' をコピーしました"));
        }
        EditorGUILayout.EndHorizontal();
    }

    /// <summary>
    /// DefineSymbolsPlatformをBuildTargetGroupに変換
    /// </summary>
    private BuildTargetGroup PlatformToBuildTargetGroup(DefineSymbolsPlatform platform)
    {
        return platform switch
        {
            DefineSymbolsPlatform.Android => BuildTargetGroup.Android,
            DefineSymbolsPlatform.iOS => BuildTargetGroup.iOS,
            DefineSymbolsPlatform.PC => BuildTargetGroup.Standalone,
            _ => BuildTargetGroup.Standalone
        };
    }
}
#endif

3

Discussion

ログインするとコメントできます