Use this class attribute to register ObjectSelector search engines automatically. Search engines with this attribute must implement the IObjectSelectorEngine interface.
The following example shows how to create a new search engine that gets invoked when the user wants to select a material for a decal object.
using System; using System.Collections.Generic; using System.Linq; using UnityEditor; using UnityEngine; using UnityEditor.Search; using UnityEditor.SearchService; using UnityEngine.Search; class DecalPicker { [QueryListBlock("Decal", "Shader", "shader")] class ShaderDecalBlockList : QueryListBlock { public ShaderDecalBlockList(IQuerySource source, string id, string value, QueryListBlockAttribute attr) : base(source, id, value, attr) { } public override IEnumerable<SearchProposition> GetPropositions(SearchPropositionFlags flags = SearchPropositionFlags.None) { yield return new SearchProposition(category: null, "HDRP Decal", "Decal", icon: GetShaderIcon() as Texture2D); yield return new SearchProposition(category: null, "URP Decal", "DecalURP", icon: GetShaderIcon() as Texture2D); } } const string k_Id = "decal_selector"; const string k_Name = "Decal Material Selector"; internal static Texture GetShaderIcon() => EditorGUIUtility.Load("Shader Icon") as Texture; internal static Texture GetMaterialIcon() => EditorGUIUtility.Load("Material Icon") as Texture; [AdvancedObjectSelectorValidator(k_Id)] static bool CanOpenSelector(ObjectSelectorSearchContext selectContext) { if ((selectContext.visibleObjects & UnityEditor.SearchService.VisibleObjects.Assets) == 0) return false; if (!selectContext.requiredTypes.All(t => typeof(Material).IsAssignableFrom(t))) return false; if (!selectContext.editedObjects.All(o => o?.GetType().Name.Contains("decal", StringComparison.OrdinalIgnoreCase) ?? false)) return false; var dbName = EnsureDecalPropertyIndexing(); if (dbName == null) return false; return true; } [AdvancedObjectSelector(k_Id, k_Name, 1)] static void SelectObject(AdvancedObjectSelectorEventType evt, in AdvancedObjectSelectorParameters args) { var selectContext = args.context; var dbName = EnsureDecalPropertyIndexing(); if (evt != AdvancedObjectSelectorEventType.OpenAndSearch) return; var selectHandler = args.selectorClosedHandler; var trackingHandler = args.trackingHandler; var query = SearchService.CreateContext(CreateDecalProvider(), $"a={dbName} t={selectContext.requiredTypeNames.First()} shader=Decal"); var viewState = new SearchViewState(query, CreateDecalsTableConfiguration(), SearchViewFlags.TableView | SearchViewFlags.OpenInBuilderMode | SearchViewFlags.DisableSavedSearchQuery); viewState.windowTitle = new GUIContent("Material Decals", GetMaterialIcon()); viewState.hideAllGroup = true; viewState.title = "decals"; viewState.selectHandler = (item, canceled) => selectHandler(item?.ToObject(), canceled); viewState.trackingHandler = (item) => trackingHandler(item?.ToObject()); viewState.position = SearchUtils.GetMainWindowCenteredPosition(new Vector2(600, 400)); SearchService.ShowPicker(viewState); } static SearchProvider CreateDecalProvider() { var assetProvider = SearchService.GetProvider("asset"); var decalProvider = SearchUtils.CreateGroupProvider(assetProvider, "Decals", 0, true); decalProvider.fetchPropositions = EnumerateDecalPropositions; return decalProvider; } static IEnumerable<SearchProposition> EnumerateDecalPropositions(SearchContext context, SearchPropositionOptions options) { if (!options.flags.HasAny(SearchPropositionFlags.QueryBuilder)) yield break; var shaderIcon = GetShaderIcon() as Texture2D; yield return new SearchProposition(category: "Affects", label: "Base Color", replacement: "affectalbedo=1", icon: shaderIcon); yield return new SearchProposition(category: "Affects", label: "Normal", replacement: "affectnormal=1", icon: shaderIcon); yield return new SearchProposition(category: "Affects", label: "Metal", replacement: "affectmetal=1", icon: shaderIcon); yield return new SearchProposition(category: "Affects", label: "Ambient Occlusion", replacement: "affectao=1", icon: shaderIcon); yield return new SearchProposition(category: "Affects", label: "Smoothness", replacement: "affectsmoothness=1", icon: shaderIcon); yield return new SearchProposition(category: "Affects", label: "Emission", replacement: "affectemission=1", icon: shaderIcon); } static SearchTable CreateDecalsTableConfiguration() { return new SearchTable("decals", new SearchColumn[] { new SearchColumn("DecalsName0", "label", "name", new GUIContent("Name", GetMaterialIcon())) { width = 160 }, new SearchColumn("DecalsShader1", "#shader", "name", new GUIContent("Shader", GetShaderIcon())) { width = 150 }, new SearchColumn("DecalsBaseColor1", "#_BaseColor", "color", new GUIContent("Color", GetShaderIcon())) { width = 130 }, }); } static string EnsureDecalPropertyIndexing() { var materialDb = SearchService.EnumerateDatabases().FirstOrDefault(IsIndexingMaterialProperties); if (materialDb != null) return materialDb.name; if (!EditorUtility.DisplayDialog("Create decal material index", "Your project does not contain an index with decal material properties." + "\n\n" + "Do you want to create one now?", "Yes", "No")) return null; var dbName = "Decals"; SearchService.CreateIndex(dbName, IndexingOptions.Properties | IndexingOptions.Dependencies | IndexingOptions.Types | IndexingOptions.Keep, roots: null, includes: new string[] { ".mat" }, excludes: null, (name, path, finished) => { Debug.Log($"Material index {name} created at {path}"); finished(); }); return dbName; } static bool IsIndexingMaterialProperties(ISearchDatabase db) { if (string.Equals(db.name, "Materials", StringComparison.OrdinalIgnoreCase)) return true; return (db.indexingOptions & IndexingOptions.Properties) == IndexingOptions.Properties && (db.includePatterns.Count == 0 || db.includePatterns.Contains(".mat")); } }
Did you find this page useful? Please give it a rating:
Thanks for rating this page!
What kind of problem would you like to report?
Thanks for letting us know! This page has been marked for review based on your feedback.
If you have time, you can provide more information to help us fix the problem faster.
Provide more information
You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:
You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:
You've told us there is information missing from this page. Please tell us more about what's missing:
You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:
You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:
You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:
You've told us this page has a problem. Please tell us more about what's wrong:
Thank you for helping to make the Unity documentation better!
Your feedback has been submitted as a ticket for our documentation team to review.
We are not able to reply to every ticket submitted.