🦭

Unityのスクリプトテンプレートでnamespaceを自動指定

2024/08/26に公開

モチベーション

Unityの開発で、C#のnamespaceの機能を使い始めました。
ディレクトリの階層とnamespaceを対応づけるようにしていますが、Unityのデフォルトのスクリプトテンプレートだと、新しくファイルを作成するたびに

  • ファイル冒頭にnamespace hogehoge.fugahuga {を追加
  • ファイルの末尾に}を追加
  • class Piyo : MonoBehavior ~をインデント

する必要があり、難儀です。

そこで、csファイルの作成場所から自動でnamespaceを記述してくれるようなエディタ拡張を作ってみました。

参考

なお、スクリプトテンプレートの一般的なカスタマイズの仕方については
https://tat1kun.hatenablog.com/entry/edit_template
が参考になります。

ディレクトリ階層によってnamespaceを分ける必要はなく、プロジェクト全体で1つのnamespaceを指定できれば十分という場合は、
https://tsubakit1.hateblo.jp/entry/2016/02/08/222703
が参考になります。

この記事では、特に「ディレクトリ階層に基づいてnamespaceを自動的に設定する」方法を扱います。

結論

例えば、Assets/Scripts/Samples/Test/に新しくTestScript.csを作成すると、

TestScript.cs
using UnityEngine;

namespace Samples.Test
{
    public class TestScript : MonoBehaviour
    {
        private void Start()
        {

        }
    }
}

のように、ディレクトリ階層を自動でnamespaceの階層に読み替えて記述してくれます。

手順

1. スクリプトテンプレートを作成

まず、Assets/Editor/CustomScriptTemplatesディレクトリを作成し、その中にスクリプトテンプレートを保存します。例えば、以下のように新しいテンプレートファイルを作成します。

CustomScriptTemplate.txt
using UnityEngine;

namespace #NAMESPACE#
{
    public class #SCRIPTNAME# : MonoBehaviour
    {
        private void Start()
        {

        }
    }
}

2. エディタ拡張の作成

次に、上記のテンプレートを利用してディレクトリに応じたネームスペースを生成するエディタスクリプトを作成し、Assets/Editorディレクトリに配置します。

CreateCustomScript.cs
using UnityEngine;
using UnityEditor;
using System.IO;

public class CreateCustomScript
{
    private const string MenuItemPath = "Assets/Create/Custom C# Script";
    private const int MenuItemPriority = 80;
    private const string DefaultScriptName = "NewScript.cs";
    private const string TemplatePath = "Assets/Editor/CustomScriptTemplates/CustomScriptTemplate.txt";
    private const string ScriptsFolderPath = "Assets/Scripts/";

    [MenuItem(MenuItemPath, false, MenuItemPriority)]
    public static void CreateNewScript()
    {
        string selectedPath = GetSelectedPath();
        string filePath = ShowSaveFilePanel(selectedPath);

        if (string.IsNullOrEmpty(filePath))
        {
            // User cancelled the save operation
            return;
        }

        string scriptName = Path.GetFileNameWithoutExtension(filePath);
        string namespaceName = GetNamespaceFromPath(selectedPath);

        CreateScriptFile(filePath, scriptName, namespaceName);
        AssetDatabase.Refresh();
    }

    private static string GetSelectedPath()
    {
        string path = "Assets";
        foreach (Object obj in Selection.GetFiltered(typeof(Object), SelectionMode.Assets))
        {
            path = AssetDatabase.GetAssetPath(obj);
            if (!string.IsNullOrEmpty(path) && File.Exists(path))
            {
                path = Path.GetDirectoryName(path);
                break;
            }
        }
        return path;
    }

    private static string ShowSaveFilePanel(string initialPath)
    {
        return EditorUtility.SaveFilePanelInProject(
            "Save Script",
            DefaultScriptName,
            "cs",
            "Please enter a file name to save the script to.",
            initialPath
        );
    }

    private static string GetNamespaceFromPath(string path)
    {
        if (!path.Contains(ScriptsFolderPath))
        {
            return string.Empty;
        }

        int startIndex = path.IndexOf(ScriptsFolderPath) + ScriptsFolderPath.Length;
        return path.Substring(startIndex).Replace("/", ".");
    }

    private static void CreateScriptFile(string filePath, string scriptName, string namespaceName)
    {
        string templateContent = File.ReadAllText(TemplatePath);
        templateContent = templateContent.Replace("#NAMESPACE#", namespaceName);
        templateContent = templateContent.Replace("#SCRIPTNAME#", scriptName);

        File.WriteAllText(filePath, templateContent);
    }
}

3.使用方法

  • Unity Editorのプロジェクトビューでスクリプトを作成したいディレクトリを開き、「右クリック -> Create -> Custom C# Script」を選択します。
  • ダイアログボックスが表示されるので、作成したいファイルの名前を入力します。
  • 新しいスクリプトが選択されたディレクトリに生成され、ディレクトリに基づいたネームスペースが自動的に設定されます。


使い方(再掲)

まとめ

ディレクトリに基づいてネームスペースを自動的に設定してくれるエディタ拡張を紹介しました。
もっと良い方法、書き方などがあればぜひ教えてください。

この記事はChatGPTと一緒に書きました。

Discussion