我想要既可以使用Unity自带的筛选面板,又需要指定他去筛选我指定的文件夹下的物体,或者说我指定的物体,直接使用搜索 只能搜索一个类型,或者名称相似的,我又不想自己写面板,用原生的比较简介,所以我看了内部Api 用反射打开自带的筛选面板,并且可以自己在外面筛选好了,直接显示筛选结果,话不多说直接上代码,看得懂就看,看不懂就算,用的版本是Unity 2020.3 其他版本的内部Api可能会有改动,如果用不了 会替换的自行替换内部方法名称
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEditor;
using UnityEditor.SearchService;
using UnityEngine;
using Object = UnityEngine.Object;
namespace Editor
{
public class TestMenu
{
//private static CusTomObjectSelector selector = new CusTomObjectSelector();
[MenuItem("Test/测试代码")]
public static void OpenSearchPanelConsole()
{
SerializedProperty property =
new SerializedObject(ScriptableObject.CreateInstance<TestProperty>()).FindProperty("texture2D");
ObjectSelectHelper.OpenUnityObjSearchPanel(typeof(Texture2D), property, false, null, OnSelect, OnSelectUpdate);
}
[MenuItem("Test/测试指定获取 ")]
public static void OpenSearchPanelConsoleWithId()
{
string path = "Assets/Editor/Images";
var files = Directory.GetFiles(path);
List<int> guids = new List<int>();
var newFiles = new List<string>();
Dictionary<string,int> mapInstanceId = new Dictionary<string, int>();
foreach (var file in files)
{
if (!file.EndsWith(".meta"))
{
var newfile = file.Replace("\\", "/");
newfile = newfile.Replace(Application.dataPath, "Assets");
newFiles.Add(newfile);
var guid = AssetDatabase.LoadAssetAtPath<Texture2D>(newfile);
guids.Add(guid.GetInstanceID());
mapInstanceId.Add(newfile,guid.GetInstanceID());
}
}
int[] OnCustomSearch(string arg)
{
List<int> aaa = new List<int>();
foreach (var newFile in newFiles)
{
if (newFile.Contains(arg))
{
if (mapInstanceId.TryGetValue(newFile, out var instanceId))
{
aaa.Add(instanceId);
}
}
}
return aaa.ToArray();
}
SerializedProperty property =
new SerializedObject(ScriptableObject.CreateInstance<TestProperty>()).FindProperty("texture2D");
ObjectSelectHelper.OpenUnityObjSearchPanel(typeof(Texture2D), property, false, guids, OnSelect, OnSelectUpdate,OnCustomSearch);
}
public static void OnSelect(Object select)
{
//UnityEditor.SearchService.ObjectSelector.UnregisterEngine(selector);
if (select != null)
{
Debug.Log("选择" + select.name);
}
}
public static void OnSelectUpdate(Object select)
{
if (select != null)
{
Debug.Log("刷新" + select.name);
}
}
public static void AddMethod(int a, int b)
{
// add a method
}
}
}
public class ObjectSelectHelper
{
/// <summary>
/// 封装的直接打开Unity选择物体面板
/// </summary>
/// <param name="searchType">筛选类型</param>
/// <param name="serializedProperty">需要修改的属性</param>
/// <param name="isShowScene">是否展示场景内</param>
/// <param name="customSearchInstanceIds">自我筛选后得到的物体实例Id</param>
/// <param name="selectAction">确认选择返回</param>
/// <param name="selectUpdateAction">持续选择返回</param>
public static void OpenUnityObjSearchPanel(Type searchType, SerializedProperty serializedProperty, bool isShowScene,
List<int> customSearchInstanceIds = null, Action<Object> selectAction = null, Action<Object> selectUpdateAction = null,Func<string,int[]> customSearch = null)
{
var editorAssembly = typeof(UnityEditor.Editor).Assembly;
Type objectSelectorType = editorAssembly.GetType("UnityEditor.ObjectSelector");
PropertyInfo getProperty = objectSelectorType.GetProperty("get", BindingFlags.Static | BindingFlags.Public);
MethodInfo showMethod = objectSelectorType.GetMethod("Show", BindingFlags.NonPublic | BindingFlags.Instance,
null,
new[]
{
typeof(Type), typeof(SerializedProperty), typeof(bool), typeof(List<int>), typeof(Action<Object>),
typeof(Action<Object>)
}, null);
var DelayerType = editorAssembly.GetType("UnityEditor.Delayer");
var createMethod = DelayerType.GetMethod("Debounce", BindingFlags.Static | BindingFlags.Public);
var m_DebounceField = objectSelectorType.GetField("m_Debounce", BindingFlags.Instance | BindingFlags.NonPublic);
var m_ListAreaInfo = objectSelectorType.GetField("m_ListArea", BindingFlags.Instance | BindingFlags.NonPublic);
object[] arguments = new object[]
{
searchType,
serializedProperty,
false,
null,
selectAction,
selectUpdateAction
};
var objectSelector = getProperty.GetValue(null);
//打开面板
showMethod.Invoke(objectSelector, arguments);
//如果有自定义显示结果,直接展示自定义结果
if (customSearchInstanceIds != null && customSearchInstanceIds.Count > 0)
{
//刷新成给定列表
var m_ListArea = m_ListAreaInfo.GetValue(objectSelector);
var showObjectsInListMethod = m_ListArea.GetType()
.GetMethod("ShowObjectsInList", BindingFlags.Instance | BindingFlags.Public);
//替换刷新方法
Action<object> action = (obj) =>
{
var searchFilter = objectSelectorType.GetField("m_SearchFilter", BindingFlags.Instance | BindingFlags.NonPublic);
if (customSearch != null)
{
var newInstanceIds = customSearch.Invoke(searchFilter.GetValue(objectSelector).ToString());
if (showObjectsInListMethod != null)
{
showObjectsInListMethod.Invoke(m_ListArea, new object[] {newInstanceIds});
}
}
};
m_DebounceField.SetValue(objectSelector, createMethod.Invoke(null, new object[] {action, 0.2f}));
if (showObjectsInListMethod != null)
{
showObjectsInListMethod.Invoke(m_ListArea, new object[] {customSearchInstanceIds.ToArray()});
}
}
Debug.Log("尝试获取");
}
}
public class TestProperty : ScriptableObject
{
public Texture2D texture2D;
}