Created
January 20, 2026 23:09
-
-
Save TitanX101/78b6e36788dd40dbb658f1a80d41f92a to your computer and use it in GitHub Desktop.
This script keeps scripting define symbols in sync based on the presence of user plugins (.dll) and Unity-compiled assemblies not part of packages.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections.Generic; | |
| using System.Linq; | |
| using UnityEditor; | |
| using UnityEditor.Build; | |
| using UnityEditor.Compilation; | |
| namespace Empress.Editor { | |
| /// <summary> | |
| /// Automatically manages scripting define symbols based on the presence of specific assemblies. | |
| /// Supports user plugins (.dll) and Unity-compiled assemblies that are not part of packages. | |
| /// </summary> | |
| [InitializeOnLoad] | |
| static class ExternalDefines { | |
| // ============================================================ | |
| // CONFIG | |
| // ============================================================ | |
| static readonly (string assemblyName, string symbol)[] Rules = { | |
| ("Sirenix.OdinInspector.Editor.dll", "ODIN_INSPECTOR"), | |
| ("DOTween.dll", "DOTWEEN"), | |
| ("FMODUnity", "FMOD_UNITY"), | |
| }; | |
| // ============================================================ | |
| // INITIALIZATION | |
| // ============================================================ | |
| static ExternalDefines() { | |
| ResolveDefines(); | |
| CompilationPipeline.compilationFinished -= OnCompilationFinished; | |
| CompilationPipeline.compilationFinished += OnCompilationFinished; | |
| } | |
| static void OnCompilationFinished(object _) { | |
| InvalidateCache(); | |
| ResolveDefines(); | |
| } | |
| // ============================================================ | |
| // CORE | |
| // ============================================================ | |
| static void ResolveDefines() { | |
| var group = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget); | |
| var buildTarget = NamedBuildTarget.FromBuildTargetGroup(group); | |
| var symbolsRaw = PlayerSettings.GetScriptingDefineSymbols(buildTarget); | |
| var symbols = ParseSymbols(symbolsRaw); | |
| var changed = false; | |
| foreach (var (assemblyName, symbol) in Rules) { | |
| var hasAssembly = HasAssembly(assemblyName); | |
| var hasSymbol = symbols.Contains(symbol); | |
| if (hasAssembly && !hasSymbol) { | |
| symbols.Add(symbol); | |
| changed = true; | |
| } | |
| else if (!hasAssembly && hasSymbol) { | |
| symbols.Remove(symbol); | |
| changed = true; | |
| } | |
| } | |
| if (changed) { | |
| var updated = string.Join(";", symbols); | |
| PlayerSettings.SetScriptingDefineSymbols(buildTarget, updated); | |
| } | |
| } | |
| // ============================================================ | |
| // ASSEMBLY DETECTION | |
| // ============================================================ | |
| static bool HasAssembly(string assemblyName) { | |
| if (assemblyName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)) | |
| return PrecompiledAssemblyPaths.Any(p => p.EndsWith(assemblyName, StringComparison.OrdinalIgnoreCase)); | |
| return AssemblyNames.Any(a => a.Equals(assemblyName, StringComparison.OrdinalIgnoreCase)); | |
| } | |
| // ============================================================ | |
| // SYMBOL HELPERS | |
| // ============================================================ | |
| static HashSet<string> ParseSymbols(string raw) { | |
| if (string.IsNullOrEmpty(raw)) | |
| return new HashSet<string>(); | |
| return raw.Split(';').Where(s => !string.IsNullOrEmpty(s)).ToHashSet(); | |
| } | |
| // ============================================================ | |
| // CACHING | |
| // ============================================================ | |
| static void InvalidateCache() { | |
| _precompiledAssemblyPaths = null; | |
| _assemblyNames = null; | |
| } | |
| static string[] PrecompiledAssemblyPaths { | |
| get { | |
| _precompiledAssemblyPaths ??= | |
| CompilationPipeline.GetPrecompiledAssemblyPaths(CompilationPipeline.PrecompiledAssemblySources.UserAssembly) | |
| ?? Array.Empty<string>(); | |
| return _precompiledAssemblyPaths; | |
| } | |
| } | |
| static string[] _precompiledAssemblyPaths; | |
| static string[] AssemblyNames { | |
| get { | |
| _assemblyNames ??= CompilationPipeline.GetAssemblies().Select(a => a.name).ToArray(); | |
| return _assemblyNames; | |
| } | |
| } | |
| static string[] _assemblyNames; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment