Visual Studio Codeの拡張機能を自作してみた
こんにちは!
情熱開発部 プログラム1課の根冝です!
少し前まで真夏のような暑さが続いていたはずなのに、急に冬らしさを感じる季節になりましたね。
寒暖差で体調を崩されないよう、皆様も体調にはお気を付けください!
さて、今回はVisual Studio Codeを使って、UnityのDefine設定に応じてステータスバーの色が変化するという拡張機能を作ってみたいと思います!
拡張機能について
そもそも拡張機能とは?
そのソフトに元々存在していない機能を後から追加するプログラムのことです。
Visual Studio Code(以降「VS Code」と表記いたします)においては
- プログラミング言語ごとの入力補完
- スペルミスのチェック
- AIによる補助用の機能
- 魚やペットを飼う
などなど、大小様々な機能を追加することができます。
拡張機能を自作してみる

VS Codeの場合は左の拡張機能タブからマーケットプレイスで公開されている拡張機能を検索して入れることがほとんどだと思いますが
自作したツールを使いたかったり、普段行う操作を自動化したかったり
様々な理由で既存の拡張機能では手が届かないことがあると思います。
そのため、今回は拡張機能の作成の一連の流れを学べるように、UnityのDefine設定に応じてステータスバーの色が変化する簡単な拡張機能を作成していきたいと思います!
環境セットアップ・プロジェクトの作成
Node.js・yeomanのセットアップ
Node.jsをインストールし、Windows標準のコマンドプロンプトもしくはPowerShellで下記のコマンドを実行してください。
ひな型生成の際に使用するyeomanとVS Code Extension Generatorをインストールします。
npm install -g yo generator-code
プロジェクトの作成
VS Codeで作成したいフォルダを開いた状態でターミナルを開き
下記のコードを実行します(環境によっては実行に時間がかかることがあります)
yo code
すると、下のような画面になるはずです。

ここではプロジェクト自体の設定についていくつか質問がされるため、順番に答えていきます。
(カーソル上下で移動、エンターで決定)
最初に質問されている
What type of extension do you want to create?
は「New Extension (TypeScript)」を選択してください。
以降の質問は任意で設定して問題ありません。
今回のセットアップでは以下の内容で回答しました!
今回の各回答(クリックで開きます)
What’s the name of your extension?
→ UnityDefineWatcher
What’s the identifier of your extension?
→ (そのままEnter)
What’s the description of your extension?
→ Changes VS Code theme color by Unity project define settings.
Initialize a git repository?
→ n
Which bundler to use?
→ unbundled
Which package manager to use?
→ npm
プロジェクトの作成が終わった後に
Do you want to open the new folder with Visual Studio Code?
と聞かれるため、 Open with `code`を選んでEnterを押します。
すると、以下のようにプロジェクトが開かれます。

デバッグ方法

実行とデバッグタブに切り替え、Run Extensionボタンから拡張機能のデバッグが可能です。
デバッグを開始すると新しいVS Codeの画面が開くため
Ctrl + Shift + Pからコマンドパレットを開き、Hello Worldコマンドを試してみましょう

ウィンドウ右下に「Hello World from <プロジェクト名>」のメッセージが出てくれば正常です!
実際に拡張機能を作ってみる
ここからは実際にコードを編集し、オリジナルの機能を追加していきます!
基本的には以下2つのファイルを編集していきます。
- extension.ts(srcフォルダ内)
- package.json
コマンドの登録
まずはコマンドパレットから実行できるように、package.jsonのcontributes内に記述を追加します。
この記述によって、「Defineチェック」というコマンドがコマンドパレットから実行できるようになります。
"contributes": {
"commands": [
{
"command": "unitydefinewatcher.helloWorld",
"title": "Hello World"
},
{
"command": "unitydefinewatcher.checkDefine",
"title": "Defineチェック"
}
]
},また、VS Code起動時に拡張機能が有効化されるように、activationEventsにもonStartupFinishedを追加します。
"activationEvents": [
"onStartupFinished"
],そして、extension.ts側にはコマンドが実行された際の処理を記述していきます。
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext)
{
// console.logでログを出力できます
console.log('拡張機能が有効になりました!');
// コマンドが実行された時の処理登録
const disposable = vscode.commands.registerCommand(
'unitydefinewatcher.checkDefine',
() =>
{
checkDefine();
}
);
context.subscriptions.push(disposable);
}
export function deactivate()
{
}
// define状態をチェックする
function checkDefine()
{
console.log('まだ何もないよ!');
}ファイルを読み込んで、任意のDefineを見つける
ファイルを読み込めるように、以下のimportを追加します。
import * as fs from 'fs';
import * as path from 'path';実際にDefineを探すコードをcheckDefine関数に記述してみましょう!
Unityプロジェクトのルートフォルダが開かれていることを前提とし、
コマンドが実行された際にProjectSettingsファイルを探して、指定のDefineが定義されているかどうかを探すコードになります。
function checkDefine()
{
// ワークスペースのルートフォルダを取得
const workspaceFolders = vscode.workspace.workspaceFolders;
if (!workspaceFolders) { return; }
// ProjectSettingsファイルを探す
const rootPath = workspaceFolders[0].uri.fsPath;
const projectSettingsPath = path.join(rootPath, 'ProjectSettings', 'ProjectSettings.asset');
if (!fs.existsSync(projectSettingsPath))
{
console.log("ProjectSettingsファイルが見つかりませんでした。");
return;
}
// ファイルを読み込む
const content = fs.readFileSync(projectSettingsPath, 'utf-8');
const targetSymbol = "DANGER_MODE"; // 探したいDefine名
// 対象のDefineがあるか判定
if (!content.includes(targetSymbol))
{
vscode.window.showInformationMessage("無かったよ。");
}
else
{
vscode.window.showInformationMessage("見つけたよ!");
}
}今の段階ではまだ実行してもログしか出ません。
ステータスバーの色を変えてみる
ここからは実際に色を変えるコードを記述していきます。
まずは色を変えるための関数たちを追加しましょう。
// ステータスバーの色を変える
function setColorCustomization(color: string)
{
// VS Codeのワークスペース設定(.vscode/settings.jsonまたはワークスペース全体設定)の取得
const config = vscode.workspace.getConfiguration('workbench');
const copyCustomization = getCopyCustomization(config);
copyCustomization['statusBar.background'] = color;
copyCustomization['statusBar.noFolderBackground'] = color;
copyCustomization['statusBar.debuggingBackground'] = color;
// 設定を適用(vscode.ConfigurationTarget.Workspace = ワークスペースの .vscode/settings.json に保存される)
config.update('colorCustomizations', copyCustomization, vscode.ConfigurationTarget.Workspace);
}
// ステータスバーの色を戻す
function removeColorCustomization()
{
const config = vscode.workspace.getConfiguration('workbench');
const copyCustomization = getCopyCustomization(config);
delete copyCustomization['statusBar.background'];
delete copyCustomization['statusBar.noFolderBackground'];
delete copyCustomization['statusBar.debuggingBackground'];
config.update('colorCustomizations', copyCustomization, vscode.ConfigurationTarget.Workspace);
}
// 現在の設定を取得する
function getCopyCustomization(config: vscode.WorkspaceConfiguration): Record<string, string>
{
const colorCustomizations = config.get<Record<string, string>>('colorCustomizations') || {};
// 既存設定のコピーを作成(編集保護を回避するため)
return { ...colorCustomizations};
}大まかに説明すると
現在のワークスペース設定を取得し、その中にあるstatusBarの色設定を上書きして再度設定に保存する処理になっています。
次は、作成した関数をcheckDefine関数のdefine判定部分に記述します。
// 対象のDefineがあるか判定
if (!content.includes(targetSymbol))
{
vscode.window.showInformationMessage("無かったよ。");
removeColorCustomization(); // new!
}
else
{
vscode.window.showInformationMessage("見つけたよ!");
setColorCustomization('#ce0000'); // new!
}この状態で実行すると、以下のように通知+ステータスバーの色が変化するようになります。


チェックの処理を自動化してみる
ステータスバーの色は変化させられましたが、現状は毎回コマンドを実行する必要があります。
このままだと手間になってしまうので、自動化してみましょう!
いくつか自動化例を準備したため、activate関数内の下部に以下を追加してみましょう。
// セーブされるたびに実行されるように
const saveDisposable = vscode.workspace.onDidSaveTextDocument(
// Tips: docの情報を使えば、特定のファイルがセーブされたときの挙動を設定できます
(doc: vscode.TextDocument) =>
{
console.log("セーブされたよ");
checkDefine();
}
);
context.subscriptions.push(saveDisposable);
// VS Codeがフォーカスされる度に実行されるように
const focusDisposable = vscode.window.onDidChangeWindowState(
(windowState: vscode.WindowState) =>
{
if(windowState.focused)
{
console.log("フォーカスされたよ");
checkDefine();
}
else
{
console.log("フォーカスが外れたよ");
removeColorCustomization();
}
}
);
context.subscriptions.push(focusDisposable);なんと、何かしらファイルを保存する度や、フォーカスが切り替わる度にチェックが走るようになります!
他にも以下のようなイベントを取ることができるため、もし興味があれば試してみてください!
- デバッグ開始の取得
- vscode.debug.onDidChangeActiveDebugSession
- ファイルの変更の取得
- vscode.workspace.createFileSystemWatcher
- 開いているファイルが切り替わったことの取得
- vscode.window.onDidChangeActiveTextEditor
パッケージ化方法
README.mdが初期のままだと失敗するため、まずはお好きな説明を追加します。
# unitydefinewatcher README
拡張機能に関するいい感じの説明をここに
次に、プロジェクトのルートでターミナルを開き、下記コマンドを実行します。
npx vsce package
下記のように実行開始後にvsceパッケージのインストールを求められた場合は、yと入力してください。

作成後はターミナルに出力先フォルダが表示されるため
拡張機能タブ内右上の三点リーダーから、「VSIXからのインストール」を押して、出力されたファイルを指定します。


インストールが終わると、通常の拡張機能のように一覧に表示されるようになります。
まとめ
今回はVS Codeで簡単なUnityのDefine状態表示をしてみました。
私は初めて作った際に列選択モードを切り替えるボタンを作ってみたところ、意外と便利で手放せなくなりそうになっています…
今回は拡張機能の自作方法を紹介しましたが、
マーケットプレイス上では以下のような便利な拡張機能も公開されています!
Material Icon Theme
エクスプローラーやタブのファイルアイコンを変更する機能です。
意味のある名前のフォルダもアイコンが変わり、見やすくなります。
Project Manager
プロジェクトをまとめて管理・切り替えできるようにする機能です。
ワンクリックで切り替えられるため、ウィンドウの追加や開き直しが不要になります。
VSCode Pets
ペットが住み着きます。
意外とペットの種類がいる上に、色も豊富でとっても可愛い!
自作する場合には、他にも以下のような機能があったら便利そうだなと考えています!
- 任意のツールを実行するステータスボタン
- ファイルを保存する度に歓声が上がる機能
- 特定の命名のファイルの時だけ有効になる機能
意外と簡単に作れてしまうので、ぜひ皆さんも拡張機能を自作して作業をもっと効率化させてみてください!
【免責事項】
本サイトでの情報を利用することによる損害等に対し、
株式会社ロジカルビートは一切の責任を負いません。