2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Unityエディターそのものを拡張する 第1回タイトルバー拡張編

Last updated at Posted at 2023-02-27

はじめに

この記事は「Unityエディターそのものを拡張して作業を効率化する」から派生している全3回のうち、第1回目の記事です。
他の記事も気になる場合はこちらからご覧ください。

この記事ではUnityエディターのタイトルバーを拡張して、独自の情報を表示させるための方法と、実際にリポジトリのパス名とGitでチェックアウトしているブランチ名を表示させた例を紹介します。
image.png

ここで紹介しているツールはUnity2021.3.9f1を使用しています。
(検証していませんが、おそらくUIElementsがエディターで導入された2019.x以降であれば動作すると思います。)

どんな場面で役に立つか

リポジトリのパス名の表示

チームでゲームを作る場合、差し込みタスクへの対応やコードのレビュー待ちなど、平行して作業を進めたいタイミングがしばしばあります。その時のためにローカルに複数のリポジトリをクローンしている人も多いのではないでしょうか?
そうして複数のリポジトリのUnityを開いていると起こりがちな問題として、どのUnityエディターがどのリポジトリのものなのかわからなくなる、下手をすると途中まで作業を進めてから目的の違うリポジトリで作業してたことに気が付くなんていうことも起こりえます。
image.png
プラットフォームの設定が違う場合はタイトルバーに書かれているので見分けがつきますが、そうでない場合は特徴的な作業途中などでなければ見た目での判別は不可能なので、Projectウィンドウのコンテキストメニューから「Show in Explorer」を選んで開かれたエクスプローラーのパスを確認するなどといったことをする必要があり、積み重なるとけっこうな手間になります。パス名を表示することでタイトルバーの文字列を読めば1目でどのリポジトリのUnityエディターなのかがわかるようにできます。
また些細ではありますがどのUnityエディターがどのリポジトリか覚えておかなくていいので、本来の作業により頭のメモリを割くことが出来るようになるのも地味にうれしいです。

ブランチ名の表示

やがて開発が進みQA期間に入ると小粒な不具合の修正などでQA1、QA2、QA3...などといった同じ目的のリポジトリを複数用意し、それらのリポジトリもそれぞれ行っている作業が頻繁に変わるようなことも起こりえます。
こうなるともはやパス名を表示しているだけでは、そのリポジトリが何の作業のためのものだったのかはわからなくなってしまいます。(このチケットを対応しようと思っていたのはQA1だっけ?それとも3だったっけ?みたいなことになります。)

ブランチ名を表示する前はその度にSourceTreeに切り替え、どのリポジトリがどんなブランチにチェックアウトしていたか確認しに行っていました。
そこでブランチ名もタイトルバーに表示させることで、そのUnityエディターが何の作業のためなのかわかりやすくなり、再び余計なことを気にせず効率よくタスクを並行して進められました。

具体的な実装の紹介

それではここからは具体的な実装方法について解説していきます。

1. タイトルバーを拡張するためのメソッドの定義

タイトルバーはWindows APIのuser32.dllの関数を呼び出すことで文字列を取得したり、設定したりできます。

TitlebarExtensions.cs
    [InitializeOnLoad]
    public class TitlebarExtensions
    {
        [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);

        private static readonly string PATH_TEXT_PREFIX = "Path : ";
        private static readonly string BRANCH_TEXT_PREFIX = "Branch : ";

        static TitlebarExtensions()
        {
            // 起動時にパスを追加するようにする。
            EditorApplication.update -= ShowPathText;
            EditorApplication.update += ShowPathText;

            // シーンを開いたときにパスを追加するようにする。
            EditorSceneManager.sceneOpened -= ShowPathText;
            EditorSceneManager.sceneOpened += ShowPathText;
        }

GetWindowTextで取得したタイトルバーの文字列にまだ独自の文字列(パス名やブランチ名)が追加されていなければ、パス名やブランチ名を結合したうえで、タイトルバーに設定させるというプログラムを書いています。

2. パス名の表示

もっとも簡単な方法はApplication.dataPathをそのまま表示させてしまう方法です。
マーベラスではProjectSettingsでdataPathからリポジトリのルートへの相対パスを設定するようにして、リポジトリのルートのパスを表示しています。

TitlebarExtensions.cs
        private static void ShowPathText(Scene _, OpenSceneMode __)
        {
            var window = GetActiveWindow();
            if(window == IntPtr.Zero)
                return;

            // 現在のタイトルバーを取得
            var windowTextLength = GetWindowTextLength(window);
            var stringBuilder = new StringBuilder(windowTextLength);
            GetWindowText(window, stringBuilder, stringBuilder.Capacity);            
            var titleBarText = stringBuilder.ToString(); // これに現在のタイトルバーのテキストが入っている。

            // 現在のタイトルバーのテキストに独自の文字列があれば取り除く
            if(titleBarText.Contains(PATH_TEXT_PREFIX))
            {
                titleBarText = titleBarText.Substring(0, titleBarText.IndexOf(PATH_TEXT_PREFIX));
            }

            // パスの取得
            var dataPath = Application.dataPath;

            // タイトルバーに設定するテキストを組み立てるStringBuilder
            var titleBarTextBuilder = new StringBuilder();
            titleBarTextBuilder.Append(titleBarText);

            // タイトルバーにパス名を追加
            titleBarTextBuilder.Append(titleBarText);

            // 1.2 パス名を追加
            titleBarTextBuilder.Append(PATH_TEXT_PREFIX);
            titleBarTextBuilder.Append(dataPath);

3. ブランチ名の表示

ブランチ名はリポジトリのフォルダ直下に「.git」というフォルダがあるので、そのなかにある「HEAD」というファイルの中に書かれています。
例えば「main」ブランチにチェックアウトしている場合は次の通りです。

HEAD
ref: refs/heads/main

なのでこのファイルのrefs/heads/以下の文字列を追加します。

TitlebarExtensions.cs
    private static void ShowPathText(Scene _, OpenSceneMode __)
    {
        // 1.2 パス名を追加
        
        // 1.3 ブランチ名を追加
        var branchName = GetBranchName(gitPath); // gitPathはProjectSettingsで設定された相対パスから求める。
        titleBarTextBuilder.Append(BRANCH_TEXT_PREFIX);
        titleBarTextBuilder.Append(branchName);

        // タイトルバーにテキストを設定
        SetWindowText(window, titleBarTextBuilder.ToString());
    }
    
    /// <param name="gitPath">ProjectSettingsで設定された「.git」フォルダのパス</param>
    /// <returns>現在のブランチ名</returns>
    private static string GetBranchName(string gitPath)
    {
        var headPath = System.IO.Path.Combine(gitPath, "HEAD");

        using (var reader = new System.IO.StreamReader(headPath))
        {
            var refs = reader.ReadLine();

            // refs/heads以降の文字列だけ抜き出す。
            return refs.StartsWith("ref: refs/heads/") ? refs.Substring("ref: refs/heads/".Length) : "No Branch";
        }
    }

以上でタイトルバーにパス名やブランチ名を表示可能です。

2
3
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
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?