Lesson18-20 - Selection 类

Selection 概述

Selection 类用于在编辑器中获取当前选中的对象,只能在编辑模式下使用。通过 Selection 可以监听用户的选择变化,进而实现更多交互功能。

获取单个对象

获取选中的 Object

1
Object selectedObj = Selection.activeObject;

返回当前选中的 Object。如果未选中任何对象返回 null。如果选中了多个对象,返回第一个。

获取选中的 GameObject

1
GameObject selectedGO = Selection.activeGameObject;

返回当前选中的 GameObject。仅当选中的是 GameObject 时才有效。

获取选中的 Transform

1
Transform selectedTransform = Selection.activeTransform;

返回选中的 Transform。仅限于场景中的对象,项目资源中的预制体无法获取。

获取所有选中对象

获取所有 Object

1
2
3
4
5
6
7
Object[] objects = Selection.objects;

if (objects != null) {
foreach (Object obj in objects) {
Debug.Log("选中了:" + obj.name);
}
}

返回数组包含所有选中的对象。

获取所有 GameObject

1
2
3
4
5
6
7
GameObject[] gameObjects = Selection.gameObjects;

if (gameObjects != null) {
foreach (GameObject go in gameObjects) {
Debug.Log("选中了:" + go.name);
}
}

返回所有选中的 GameObject,包括场景对象和预制体。

获取所有 Transform

1
2
3
4
5
6
7
Transform[] transforms = Selection.transforms;

if (transforms != null) {
foreach (Transform t in transforms) {
Debug.Log("位置:" + t.position);
}
}

返回所有选中对象的 Transform。仅限于场景中的对象。

判断对象是否被选中

Contains 方法

1
2
3
4
5
6
7
GameObject targetGO = someGameObject;

if (Selection.Contains(targetGO)) {
Debug.Log("对象被选中了");
} else {
Debug.Log("对象未被选中");
}

判断指定对象是否在当前选择中。

筛选对象

GetFiltered 方法

1
2
3
4
5
// 获取 TopLevel 的 GameObject
GameObject[] filtered = Selection.GetFiltered<GameObject>(SelectionMode.TopLevel);

// 同样功能的非泛型版本
Object[] filtered2 = Selection.GetFiltered(typeof(GameObject), SelectionMode.TopLevel);

从当前选择中筛选出符合条件的对象。

SelectionMode 筛选模式

  • Unfiltered:不过滤,返回所有选中对象
  • TopLevel:只返回最上层对象,不包含子对象
  • Deep:返回对象及其所有子对象
  • ExcludePrefab:排除预制体
  • Editable:只返回可编辑的对象
  • OnlyUserModifiable:仅返回用户可修改的对象
  • Assets:只返回项目资源文件夹中的对象
  • DeepAssets:返回资源及其子资源(如子文件夹的资源)

混合多个筛选模式

1
2
3
4
// 获取场景中的最上层 GameObject(不包含预制体)
GameObject[] filtered = Selection.GetFiltered<GameObject>(
SelectionMode.TopLevel | SelectionMode.ExcludePrefab
);

使用位或 | 操作符组合多个模式。

监听选择变化

selectionChanged 事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private void OnEnable() {
Selection.selectionChanged += OnSelectionChanged;
}

private void OnDisable() {
Selection.selectionChanged -= OnSelectionChanged;
}

private void OnSelectionChanged() {
Debug.Log("选择的对象变化了");

if (Selection.activeGameObject != null) {
Debug.Log("现在选中:" + Selection.activeGameObject.name);
}
}

也可以使用 Lambda 表达式:

1
2
3
Selection.selectionChanged += () => {
Debug.Log("选择变化");
};

注意:监听事件后需要在合适的时机注销,避免内存泄漏。

实战应用

应用示例:实时更新窗口内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class MyEditorWindow : EditorWindow {
private void OnEnable() {
Selection.selectionChanged += OnSelectionChanged;
}

private void OnDisable() {
Selection.selectionChanged -= OnSelectionChanged;
}

private void OnSelectionChanged() {
Repaint(); // 重绘窗口,显示新选择的对象信息
}

private void OnGUI() {
if (Selection.activeGameObject != null) {
EditorGUILayout.LabelField("选中对象:" + Selection.activeGameObject.name);
EditorGUILayout.LabelField("位置:" + Selection.activeTransform.position.ToString());
} else {
EditorGUILayout.LabelField("未选中任何对象");
}
}
}

应用示例:批量操作选中对象

1
2
3
4
5
if (GUILayout.Button("重命名所有选中对象")) {
foreach (GameObject go in Selection.gameObjects) {
go.name = "新名字_" + go.name;
}
}