LoginSignup
4
1

More than 3 years have passed since last update.

【Unity】スクリプトの自動コンパイルを抑制&ショートカットキーでコンパイルする【エディタ拡張】

Last updated at Posted at 2020-12-30

はじめに

新規スクリプトの追加や移動でいちいちコンパイルが走ると開発のイテレーション速度が落ちるので

  • Unityの自動コンパイルを抑制
  • ショートカットキー or メニューから実行することで明示的にコンパイルする

という挙動を実現するエディタ拡張を書いてみた。

ちなみにこれまで無駄なコンパイルが走ってほしくないときは自分も@mao_さんと同じやり方でやっていた。

2021/1/2 更新

  • スクリプトの変更が検知されない不具合修正
  • 再生後に Tools/Compile Locker/Compile でコンパイルが走らない不具合修正

更新ここまで

動作環境

  • macOS Catalina(10.15.6)
  • Unity2019.4.16

にて動作確認。

ソースコード

CompileLocker.cs
#if UNITY_EDITOR
using System;
using System.Threading.Tasks;
using UnityEditor;
using UnityEditor.Compilation;
using UnityEngine;

[InitializeOnLoad]
public class CompileLocker
{
    private const string MenuItemPath = "Tools/Compile Locker/";

    public class CompileLockerData : ScriptableSingleton<CompileLockerData>
    {
        public bool isInitialized;
        public bool isLocking;
    }

    static CompileLocker()
    {
        Debug.Log("Assemblies reloaded.");

        Lock();

        if (isInitialized) return;
        isInitialized = true;

        Debug.LogWarning($"Disabled auto compiling. For manual compiling, execute \"{MenuItemPath}Compile\".");
    }

    private static bool isInitialized
    {
        get => CompileLockerData.instance.isInitialized;
        set => CompileLockerData.instance.isInitialized = value;
    }

    private static bool isLocking
    {
        get => CompileLockerData.instance.isLocking;
        set => CompileLockerData.instance.isLocking = value;
    }

    private static void Lock()
    {
        if (isLocking) return;

        EditorApplication.LockReloadAssemblies();
        isLocking = true;
    }

    private static void Unlock()
    {
        if (isLocking == false) return;

        EditorApplication.UnlockReloadAssemblies();
        isLocking = false;
    }

    private static Task _compileTask = null;

    [MenuItem(MenuItemPath + "Compile %r", false)]
    private static void ReloadAssemblies()
    {
        if (_compileTask != null) return;

        _compileTask = CompileTask().ContinueWith(_ => _compileTask = null);
    }

    private static async Task CompileTask()
    {
        AssetDatabase.Refresh();
        Unlock();

        if (EditorApplication.isCompiling)
        {
            Debug.Log("Compiling...");

            // 連打防止
            while (EditorApplication.isCompiling)
            {
                await Task.Delay(TimeSpan.FromSeconds(0.5f));
            }
        }
        else
        {
            Debug.Log("Nothing to compile.");
            Lock();
        }
    }

    [MenuItem(MenuItemPath + "Force Compile %#r")]
    private static void ForceCompile()
    {
        AssetDatabase.Refresh();
        Unlock();
        Debug.Log("Compiling...");
        CompilationPipeline.RequestScriptCompilation();
        // NOTE: 必ずアセンブリのリロードが走るのでstaticコンストラクタでロックされる
    }
}
#endif

挙動

  • プロジェクトに入れるだけでUnityの自動コンパイルを抑制する
  • ⌘ + R もしくは Tools/Compile Locker/Compile
    • →必要に応じて通常のコンパイルを走らせる
  • ⌘ + shift + R もしくは Tools/Compile Locker/Force Compile
    • →プロジェクト内のスクリプトをすべて強制的にコンパイルする

Windosの場合は Ctrl に読み替えてください。

ショートカットキーが被る

  • ⌘ + RAssets/Reimport と被る
  • ⌘ + shift + R :Extenject(Zenject)の Validate Then Run と被る

ので、適当に変更したほうがいいです。「被ったら両方実行」とかできないんだろうか。

ハマったポイント

コンパイルが走らない1

EditorApplication.UnlockReloadAssemblies();
EditorApplication.LockReloadAssemblies();

みたいなコードだとコンパイルが走らないので EditorApplicaion.delayCall を使って再ロックをちょっと遅らせたり EditorApplication.update を1回待ったりしたけどうまくいかなかった。

コンパイルが走らない2

CompileChecker.cs を編集した場合は ⌘ + R でコンパイルしようとしてもなぜかコンパイルが走らず、 CompileChecker.cs を先に Reimport してから ⌘ + R する必要がある。謎
AssetDatabase.Refresh() で解決しました。

注意

当然再生中もコンパイルが走らなくなります。あと自動コンパイルが走らない挙動はUnityがおかしくなったと勘違いされると思うので、チーム開発ではこのスクリプトを .gitignore に登録するのを忘れずに。

所感

Assembly Definition( .asmdef )ファイルと合わせて使うとさらに無駄なコンパイルを減らせそう。

...記事を書き終わってから「Rider上でファイル操作すればいいのでは?🤔」と思った。

参考

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1