はじめに
今回はSelection Groups
について取り上げたいと思います。
Selection Group
はUnity公式パッケージで、複数のGameObject
をグループ化・操作することができます。
Selection Group は、Unity のワークフローをより快適にします。 複数の GameObject を共通の名前でグループ化して、グループ単位で操作を行うことができます。
またGoQL
という条件を満たすGameObject
を抽出する機能は非常に便利なので是非習得してみるとよいと思います。
GoQL は「GameObject Query Language」の略です。 シーンのヒエラルキーから GameObject のセットを構築するために使用されます。
この API は単一のクエリ文字列をパラメーターとして受け取り、そのクエリにマッチする GameObject のセットを返します。
GoQL オーバービュー | Selection Groups | 0.9.1-preview
ただ現段階(2023/4/9時)ではExperimental
パッケージで中身が変更される可能性もあります。注意してください。
インストール方法
メニューバーのWindow -> PackageManager
からPackage Manager
を立ち上げ、Add package from git URL
にて以下の文字列を入力し、Add
ボタンを押せばインストールできます。
com.unity.selection-groups
使い方
Selection Groups Windowの立ち上げ方法
メニューバーのWindow -> General -> Selection Groups
を選択し、Selection Groups Window
を立ち上げます。
Selection Groupの作成
Selection Groups Window
の+
ボタンを押し、Create Empty Group
を選択すると、Hierarchy
にSelectionGroup
コンポーネントがアタッチされたGameObject
が生成されます。
Selection GroupにGameObjectを追加する
Hierarchy
から対象のGameObject
をSelection Groups
の対象Selection Group
へとドラッグ&ドロップします。
このときSelection Group
コンポーネントがアタッチされているGameObject
と階層構造になるわけではないということに注意してください。
Selection Groupコンポーネント
プロパティ | 説明 |
---|---|
Group name | GameObject グループの名前と同じです。 |
Color | Selection Groups Window に表示されているグループのカラーです。 |
Group Query | クエリを指定すると、そのクエリに合致する階層の GameObject を自動的にグループに割り当てます。詳しくは、GoQL のドキュメントを参照してください。 |
Group name
まずGroup name
を変更すると、GameObject
の名前も連動して変更されます。
Color
Color
に関してはSelection Groups Window
に表示されるグループカラーを変更することができます。
Group Query
Group Query
はSelection Groups
の一番特筆すべき機能といってもよいでしょう。
Group Query
はGoQL(GameObject Query Language)という、イメージSQL
のGameObject
版のような問い合わせ言語を用いて、条件に合ったGameObject
を自動的にグループに割り当てることができます。
クエリを指定すると、そのクエリに合致する階層の GameObject を自動的にグループに割り当てます。
例えば*Manager
とGroup Query
に記載すると、GameManager
のようにManager
で終わるGameObject
をグループに割り当てることができます。
グループに対して何かしらの操作をする
Hierarchy上
グループ内のGameObject
をHierarchy
上ですべて選択したい場合は、グループをダブルクリックするか、グループ上で右クリックしてSelect All Group Members
を選択します。
スクリプト上
コード上では、SelectionGroup
コンポーネントに対して以下のコードを書くことでアクセスすることができます。
public class Test : MonoBehaviour { [SerializeField] private SelectionGroup selectionGroup; private void Start() { // グループ内のゲームオブジェクトを取得する IList<GameObject> gameObjects = selectionGroup.Members; // 非アクティブにする foreach (var item in gameObjects) { item.SetActive(false); } } }
補足
インストールするとPackages/Selection Groups
にパッケージが入るわけですが、そこまで規模の大きなものではないので割と読みやすく参考になったりします。
フォルダ構成とか、Test
の書き方、AssemblyInfo.cs
とか結構参考になります。
というかチラッと眺めていたら気づいたのですが、Unity公式のパッケージなのにハンガリアン記法使っていないのですね。
// MonoBehavior.cs namespace UnityEngine { /// <summary> /// <para>MonoBehaviour is a base class that many Unity scripts derive from.</para> /// </summary> [NativeHeader("Runtime/Mono/MonoBehaviour.h")] [NativeHeader("Runtime/Scripting/DelayedCallUtility.h")] [RequiredByNativeCode] [ExtensionOfNativeClass] public class MonoBehaviour : Behaviour { private CancellationTokenSource m_CancellationTokenSource; // 以下省略
// SelectionGroups内のコード namespace Unity.SelectionGroups { /// <summary> /// A HashSet which retains order of items as they are added or inserted. /// or /// A List which only contains unique references. /// </summary> /// <typeparam name="T"></typeparam> internal class OrderedSet<T> : IList<T> { List<T> items = new List<T>(); HashSet<T> uniqueIndex = new HashSet<T>(); public IList<T> List => items; public T this[int index] { get => items[index]; set => items[index] = value; } public int Count => items.Count; public bool IsReadOnly => false; public void Add(T item) { if(!uniqueIndex.Contains(item)) { items.Add(item); uniqueIndex.Add(item); } } public void Clear() { items.Clear(); uniqueIndex.Clear(); } public bool Contains(T item) { return uniqueIndex.Contains(item); } public void CopyTo(T[] array, int arrayIndex) { items.CopyTo(array, arrayIndex); } public IEnumerator<T> GetEnumerator() { return items.GetEnumerator(); } public int IndexOf(T item) { return items.IndexOf(item); } public void AddRange(IEnumerable<T> objectReferences) { foreach (var i in objectReferences) { Add(i); } } public void Insert(int index, T item) { if(!uniqueIndex.Contains(item)) { items.Insert(index, item); uniqueIndex.Add(item); } } public bool Remove(T item) { uniqueIndex.Remove(item); return items.Remove(item); } public void Remove(IList<T> items) { uniqueIndex.ExceptWith(items); foreach(var i in items) { this.items.Remove(i); } } public void RemoveAt(int index) { var item = items[index]; uniqueIndex.Remove(item); items.RemoveAt(index); } IEnumerator IEnumerable.GetEnumerator() { return items.GetEnumerator(); } } }
昔の名残なのか何でこんな変数名つけてんだろうなとか思っていた(もしかしたらC++
のエンジン側の影響??)のですが、パッケージの中身は割とMicrosoft
の規約に従っていそうな雰囲気を感じました。
ちょっと面白かったので補足として掲載しておきます。