Unity3D
Unity
Unity拡張
Unity2D
UnityEditor

【Unity】MenuItemで指定したショートカットキーを無効化する


はじめに

Unityのエディタ拡張にはMenuItemを使ってショートカットキーを登録する方法があります。

参考:http://baba-s.hatenablog.com/entry/2013/12/13/101637

この方法でだれでも手軽にショートカットキーを登録することができます。

[MenuItem("Custom/Pause _p")]

private static void Pause()
{
if(!EditorApplication.isPlaying)
{
return;
}

EditorApplication.isPaused = true;
}

例えば上記のようなコードがあったとすると、これは「p」を押すだけでプレイ中に一時停止することができます。

Unityの標準のままだと「Ctrl+Shift+P」を入力しないといけないのでとても楽になったのがわかります。


問題点

実は先ほどのコード、少し問題点があります。

それはEditor上での「p」入力を全て受け取ってしまい、GameObjectやファイルのリネーム時に「p」が入力できなくなってしまうことです。

そこでUnityのMenuItemリファレンスを見てみました。

https://docs.unity3d.com/jp/530/ScriptReference/MenuItem.html

この中の

[MenuItem("MyMenu/Log Selected Transform Name")]

static void LogSelectedTransformName()
{
Debug.Log("Selected Transform is on " + Selection.activeTransform.gameObject.name + ".");
}

[MenuItem("MyMenu/Log Selected Transform Name", true)]
static bool ValidateLogSelectedTransformName()
{
// Return false if no transform is selected.
return Selection.activeTransform != null;
}

この記述。

これはMenuItemの機能で、MenuItemの第二引数をtrueにしたValidateメソッドを用意してやることで、メニューを表示した際に実行可能かチェックするものです。

これを見る限り、現状の問題を解決してくれそうな気がしますが、残念ながらこれでは解決されません。

確かにメニューに表示した際は無効化され、メソッドは呼ばれなくなっていますが、しっかりとショートカットキー入力は受け取っているようです。


解決策

[MenuItem("Custom/Pause _p")]

private static void Pause()
{
if (!EditorApplication.isPlaying)
{
var window = EditorWindow.focusedWindow;
if (window != null)
{
window.SendEvent(Event.KeyboardEvent("p"));
}

return;
}

EditorApplication.isPaused = true;
}

ということで、MenuItemで指定したメソッドが呼ばれてしまうのは受け入れて、その中で新しくキーイベントを発光する方法をとりました。

var window = EditorWindow.focusedWindow;

if (window != null)
{
window.SendEvent(Event.KeyboardEvent("p"));
}

変更点はここです。

ここでは、まず現時点でフォーカスが当てられているWindowを取得します。

そのWindowに対して、KeyboardEventを発行してSendEventにて送っています。

こうすることによって、実際にはショートカットキーで呼ばれていますが、呼ばれていないように誤魔化すことができます。


まとめ

今回はショートカットキーを無効化にする方法を紹介しました。

ただ、この方法だと一部無効化しきれないこともあるので、ご注意ください。

ほかにいい方法があればお教えいただけると嬉しいです。

感想、意見などお待ちしております。

https://twitter.com/_ykringo