Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
1
Help us understand the problem. What are the problem?

posted at

【Unity】スペースキーでGameObjectのアクティブ状態をトグル(on/off)できるようにする【エディタ拡張】

はじめに

前は GameObject のon/off切り替え用に QuickToggle を使ってHierarchy上に☑を表示してたのですが、「 GameObject を選択してスペースキーで切り替えできれば☑のUIいらないのでは?」と思ったので作ってみました。思いの外つまづきポイントが多かったのでメモ。

ちなみに

  • 非再生時も動作
  • Shortcut Managerからショートカットキーを変更可能
    • スペースキー以外でトグルできる
  • Git管理でチームメンバーと機能を共有可能

です。

TL;DR

  1. 適当なディレクトリを作る
    • Assets/Scripts/Editor/ToggleActiveStateShortcut とか
  2. ↑のディレクトリに ForInternalAccess.asmref を追加
    • 作り方は *.asmdef とほぼ同じ
    • Projectウィンドウ右クリック → CreateAssembly Definition Reference
  3. ForInternalAccess.asmrefAssembly DefinitionUnityEditor.UI を指定する
  4. ForInternalAccess.asmref と同じディレクトリに以下のスクリプトを追加する。
ToggleActiveStateShortcut.cs
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.ShortcutManagement;
using UnityEngine;

class ToggleActiveStateShortcut
{
    [Shortcut("Hierarchy/Toggle Active State", typeof(SceneHierarchyWindow), KeyCode.Space)]
    private static void ToggleActiveState()
    {
        EditorApplication.ExecuteMenuItem("GameObject/Toggle Active State");
    }
}
#endif

結果:
スクリーンショット 2021-09-21 20.36.29.png

解説

*.asmref ファイルについて

*.asmrefAssembly DefinitionUnityEditor.UI を指定することでUnityの internal クラスにアクセスできるようにします。これをやらないと typeof(SceneHierarchyWindow) でコンパイルエラーになります。

*.asmref について詳しくは以下の記事を参照のこと。

SceneHierarchyWindow を参照できるなら *.asmref を使わないやり方でもOK。

ShortcutAttribute について

MenuItemAttribute, [MenuItem(..)] でいいのでは?

MenuItemAttribute, [MenuItem(..)] を使えばわざわざ internal アクセスする必要がないのですが、試しに以下のスクリプトを配置してみると、

[MenuItem("Tools/Toggle Active State _SPACE")]
private static void ToggleActive()
{
    // 処理
}
  • Animation/Play Animation
  • Timeline/Play

の2つとコンフリクトすることがわかります。

ちなみに [MenuItem] でスペースキーを指定したい場合は

[MenuItem("Tools/FooBar _SPACE")]

みたいに _SPACE を指定します。以下はどれもうまくいきません。

  • space
  • Space
  • SPACE
  • _space
  • _Space

最初これでやろうとしてググってもやり方がヒットしなくて苦労しました。

Main Menu/GameObject/Toggle Active State でいいのでは?

もともとUnityには選択した GameObject のオンオフを切り替えるショートカットがあり、Macだと option + shift + A が割り当てられています。

スクリーンショット_2021-09-21_19_26_43.png

チームメンバーと共有しない場合はShortcut Managerからこのショートカットにスペースキーを割り当てればやりたいことは実現できます。コンフリクトする旨が表示されますが Create Conflict を選べばOK。

スクリーンショット 2021-09-21 19.31.33.png

ちなみに最初に載せたコードでは最終的にはUnityにもとからある Main Menu/GameObject/Toggle Active State を呼び出しています。

ShortcutAttribute, [Shortcut(..)] については「AnimationとTimelineが同じスペースキーでコンフリクトしないなら方法があるはずだ」と思ってTimelineのソースコード読んでたら見つけました。

[MenuItem(..)][Shortcut(..)] の違い

[MenuItem]

  • メニューに項目が追加される
  • ショートカットがグローバルに定義される
    • 他で同じキーが割り当てられてるとコンフリクトする

[Shortcut]

  • メニューに項目が追加されない
  • ショートカットがウィンドウのローカル内に定義される(たぶん)
    • 他のウィンドウで同じキーが割り当てられててもコンフリクトしない

余談

Shortcutsウィンドウの上のほうに表示されてるキーボードにもいろいろ機能があって、下のコマンドをキーボードにDrag&Dropでショートカットキーを設定できたりしてビビった。思ったより高機能。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
1
Help us understand the problem. What are the problem?