Scripting Define Symbols
プリプロセッサはビルドに問題を抱えがちなUnity
には欠かせないものですが、
Scripting Define Symbols
はなんというか……もうちょっと、こう、やりようというものが……。
【Unity】Scripting Define Symbolsを簡単に設定できるようにするエディタ拡張
Scripting Define Symbolsを劇的に使いやすくするエディタ拡張【Unity】【エディタ拡張】
みたいな話をしたいのですが、既に先人がScripting Define Symbols
とはなんぞや? という説明からなにからエディタ拡張で操作するとことまで書いてくれてるからそっち読んどいてくれよな!
おしまい。
DefineSwitcher.cs
なんか何も考えないで書いてたら記事が終わったんですが、そういうことではなくてわたしも同じようなものを作ってみましたという話です。
1シンボルしかON/OFFできませんが、その分簡単にエディタメニューからポチポチ切り替えられるのがポイントです。
エディタの初回起動時とSwitch Platform
のタイミングでScripting Define Symbols
をチェックして、エディタメニューのON/OFFを切り替えています。
gist
に載せたものは特定のプラットフォーム1に向けた記述になっているので、コメントに書いたとおりDefine
とDefineMenuPath
を書き換えて使ってください。
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.Build;
using UnityEngine;
namespace Nekomimi.Daimao
{
/// <summary>
/// Switch #define.
/// rewrite <see cref="Define"/> and <seealso cref="DefineMenuPath"/>
/// </summary>
public class DefineSwitcher : IActiveBuildTargetChanged
{
#region Define
private const string Define = "UNITY_OVR";
private const char Separator = ';';
private static void SetDefine(bool on)
{
if (on == IsDefined())
{
return;
}
var current = new HashSet<string>(CurrentDefines());
if (on)
{
current.Add(Define);
}
else
{
current.Remove(Define);
}
PlayerSettings.SetScriptingDefineSymbolsForGroup(
EditorUserBuildSettings.selectedBuildTargetGroup, string.Join(Separator.ToString(), current)
);
}
private static IEnumerable<string> CurrentDefines()
{
return PlayerSettings.GetScriptingDefineSymbolsForGroup(EditorUserBuildSettings.selectedBuildTargetGroup).Split(Separator);
}
private static bool IsDefined()
{
return CurrentDefines().Contains(Define);
}
#endregion
#region EditorMenu
private const string DefineMenuPath = "Oculus/" + Define;
[MenuItem(DefineMenuPath, priority = -1)]
private static void SwitchDefine()
{
var current = IsDefined();
SetDefine(!current);
SetCheckState(!current);
}
private static void SetCheckState(bool state)
{
var check = Menu.GetChecked(DefineMenuPath);
if (state == check)
{
return;
}
Menu.SetChecked(DefineMenuPath, !check);
}
#endregion
#region IActiveBuildTargetChanged
public int callbackOrder { get; } = 0;
public void OnActiveBuildTargetChanged(BuildTarget previousTarget, BuildTarget newTarget)
{
SetCheckState(IsDefined());
}
#endregion
#region InitializeOnLoadMethod
private class FirstLoad : ScriptableSingleton<FirstLoad>
{
[SerializeField]
public bool AlreadyLoaded = false;
}
[InitializeOnLoadMethod]
private static void CheckOnLaunch()
{
if (FirstLoad.instance.AlreadyLoaded)
{
return;
}
FirstLoad.instance.AlreadyLoaded = true;
SetCheckState(IsDefined());
}
#endregion
}
}
まとめ
こういうプリプロセッサとかマクロとかってあんまり使わない派なのですが、今回はそこそこつらいことがあったので作りました。
Unity
のエディタ拡張ってなんだかんだAPI
が用意されているので、作ろうと思えばなんでも作れますね。
公式のマニュアルが*……ふわっ……*としているので先人の記事を探し出さなければならないのが苦しいところですが、これからはエディタ拡張で解決できる問題がないか、気に留めてみようと思います。
おしまい。
参考
【Unity】Scripting Define Symbolsを簡単に設定できるようにするエディタ拡張
Scripting Define Symbolsを劇的に使いやすくするエディタ拡張【Unity】【エディタ拡張】
【Unity】UnityEditor の起動時にのみ処理を行う2