勉強不足で至らんブログ

勉強不足ですが色々と書いていきます。

UnityEditorのTitlebarにディレクトリの場所を表示する

この記事はUnity Advent Calendar 2019の8日目の記事です。

レビューをするときにEditorを複数起動する

業務でも業務でなくてもコードレビューをすることがあると思います。そして、PRにもよりますがEditorで挙動確認をしたいことがあります。 その時に、自分のタスクでbranch切ってるUnityEditorで一旦PRのブランチを切ってレビューをすることもありましたが、ブランチを切ってImportさせるのは時間を食います。

そこで、私は別のReviewディレクトリを作ってそこにProjectをcloneしてレビューをするようにしてます。

ex. Unity Project ディレクト

├── A (Repository root)

└── Review

   └── A' (Repository root)

※AとA'は同じgit Repository

例えば上記のように、Aは自分のタスクを行う場所、Reviewディレクトリ配下はレビューを行う場所としておけばUnityの多重起動をしてスムーズに切り替えれると思います。レビューのProjectをImportする間は自分のタスクが行えるので時間の無駄にもなりにくいです。

ただここで問題が起こります。 Unityの多重起動をすると、Editorの違いが見た目でわかりません!どっちがレビュー用だっけ?となりがちです。

そこで、最初はEditorの色を変えればいいかなと思いましたが無料で個人開発で同じようなことをする場合にできないこともあると思ったのでUnityEditor WindowのTitlebarを変えることにしました。(そのためWindows専用の処理になっています)

gistはこちら MizoTake/ChangeEditorTitlebar

できたもの

before after
before.jpg review.jpg

今回のEditor拡張の有無です…地味ですがTitlebarの後ろに「Review」という文字が追加されています。 正直、わかりづらいですがこれでReview用のUnityEditorかどうか判別が可能になります。

実装

using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;

namespace ChangeEditorTitlebarFromPath
{
#if UNITY_EDITOR_WIN
    [InitializeOnLoad]
    public class ChangeEditorTitlebar
    {
        
        [DllImport("user32.dll")]
        static extern IntPtr GetActiveWindow();
        
        [DllImport("user32.dll", EntryPoint = "SetWindowText")]
        static extern bool SetWindowText(System.IntPtr hwnd, System.String lpString);
        
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern int GetWindowTextLength(IntPtr hWnd);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
        
        static ChangeEditorTitlebar()
        {
            // 検索対象の文字列をディレクトリパスに含まれているかどうか判別
            var target = "Review";
            var path = Application.dataPath;
            var isMatch = Regex.IsMatch(path, target);
            if (!isMatch) return;
            
            // 現在ActiveなWindowを取得(InitializeOnLoadでUnityEditorが選択されている前提)
            var window = GetActiveWindow();
            if (window == IntPtr.Zero) return;
            
            // 既にあるWindowの文字列を取得
            var length = GetWindowTextLength(window);
            var stringBuilder = new StringBuilder(length + 1);
            GetWindowText(window, stringBuilder, stringBuilder.Capacity);
            
            // 取得した文字列の後ろに今回の検索対象の文字列を追加
            var titleBarText = stringBuilder.ToString();
            SetWindowText(window, titleBarText + $" - {target}");
        }
    }
#endif
}

かなりシンプルです。この1ファイルのみを追加すれば大丈夫です。 Windowsのみですが、これで用途別に同じプロジェクトを開いても判別できると思います。

さいごに

これで一旦、用途別のWindowの判断が可能になりました。タスク用途とReviewで分けるのであれば有料版を持っていればEditorの色を黒とデフォルトで分ければいいのですが、無料版や3つ以上となるとTitlebarになるのかなと思いました。 拡張をいれるとするならプロジェクト内ではなくてUnity.exe単位の拡張で行うのが良いのかなと思っています。