改进 Prefab Center
之前已经初步实现了 Prefab Center 的基本功能,可以显示 Asset/Prefabs
路径下附带有 PrefabCenterItem
组件的 Prefab 并可以将其加入到场景中。现在进一步对其进行改进,借此讨论 EditorWindow
类下其它一些重要的方法。
资源自动更新
在 Assets/Tools/PrefabCenter/Editor/PrefabCenter.cs
中添加以下代码,从而新增或移除 Prefab 时,Prefab Center 也会有对应的更新。
private void OnProjectChange () {
_prefabItems.Clear ();
_prefabItems = GetPrefabsFromAssetDatabase ();
Repaint ();
}
道理很简单,当 Project 视图发生变化(即路径下的 Prefab 发生修改时),清空并重新收集路径下的 Prefab 并重绘窗口。
复制和删除
复制指定的 Prefab:
private void DuplicatePrefab () {
string newName = _shownItem.name;
int count = 0;
while (AssetDatabase.FindAssets (newName, new string [] { "Assets/Prefabs" }).Length > 0) {
List<string> nameSlots = new List<string> (newName.Split (' '));
string lastSlot = nameSlots [nameSlots.Count - 1];
if (Regex.IsMatch (lastSlot, @"^-?\d+$")) {
nameSlots.RemoveAt (nameSlots.Count - 1);
count = int.Parse (lastSlot) + 1;
} else {
count++;
}
newName = string.Join (" ", nameSlots.ToArray ()) + " " + count.ToString ();
}
PrefabUtility.CreatePrefab (string.Format ("Assets/Prefabs/{0}.prefab", newName), _shownItem);
}
复制的操作由 PrefabUtility.CreatePrefab
实际完成,主要在新 Prefab 的命名上做了一些判断和操作。
删除指定的 Prefab:
private void DeletePrefab () {
string path = AssetDatabase.GetAssetPath (_shownItem);
if (EditorUtility.DisplayDialog (
"Delete selected prefab?",
"\t" + path + "\n\nYou cannot undo this action.",
"Delete",
"Cancel"
)) {
AssetDatabase.DeleteAsset (path);
_showDetail = false;
}
}
AssetDatabase.DeleteAsset
根据路径删除资源,代码添加了确认对话框。
在 Project 视图中找到对应 Prefab
private void OnDetailGUI (int id) {
// ...
if (GUI.Button (new Rect (5, 42, _detailPosition.width - 10, 17), "Show in project")) {
EditorGUIUtility.PingObject (_shownItem);
Selection.activeObject = _shownItem;
}
// ...
}
EditorGUIUtility.PingObject
产生高亮, Selection.activeObject
选中该 Prefab。
Unity 还提供了工具类如EditorUtility
和EditorGUIUtility
,包含很多有用的方法,可以帮助开发者更好的扩展编辑器。例如前边用到的EditorUtility.DisplayDialog
确认对话框、EditorGUIUtility.PingObject
产生高亮等等。