Custom SearchProvider doesn't call onDisable when window is closed

Hi, I’m not sure if this is a bug. I’m making a custom SearchProvider. I register it like they do in the example, with the SearchItemProvider Attribute. I’ve found a couple of obstacles in the way, but it’s not been too hard so far. The Search API is very thorough. The first obstacle was that my provider wasn’t being used after I added it. Restarting the Unity Editor fixed it; it’s not ideal but it’s workable.

Now I’ve found another problem that is turning out to be quite inconvenient. I want to use onDisable to clear some cached data that can get really big. The docs say it’s called when the SearchWindow is closed and suggest this is the ideal place to clear caches, but my callback doesn’t get called when closing the window.

Is there something I need to do to ensure my provider is disabled when the window is closed?
I’d really appreciate any pointers if someone is familiar with the Search API.
Thank you very much.

Hi @oscarAbraham ,

It is cool that you are trying to write your own Search Provider. I will ask you a bunch of questions to clarify your workflow . Hopefully this will give me enough information to help you solve this issue:

  • Which version of Unity are you using?
  • How are you registering your SearchProvider? I suppose you are using the [SearchProvider] attribute.
  • Can you share the code to your SearchProvider? This is optional, but it can help me debug your issue.
  • Last question is for my own personal interest: what is the purpose of your SearchProvider? What are the objects you are searching for? Creating a SearchProvider is an advance workflow and I like to understand the Search use cases of our clients.

Thanks,

Sebastien

Hi! Thank you very much for this.

  • I’m using Unity 6000.0.30.
  • I am using the SearchItemProviderAttribute to register the SearchProvider, as the docs suggest. Is there another way to do it?
  • I’d need to share a lot of code for the actual provider I made to make sense. That said, I tried with a plain, barebones provider and onDisable still doesn’t run there:
    public class TestSearchProvider : SearchProvider
    {
        public TestSearchProvider() : base("testprovider", "Test Search Provider")
        {
            fetchItems = (ctx, items, provider) => FetchItems(ctx, provider);
            onEnable = () => Debug.Log("Enabled");
            // "Disabled" is never printed.
            onDisable = () => Debug.Log("Disabled");
        }

        [SearchItemProvider]
        public static SearchProvider CreateProvider()
        {
            return new TestSearchProvider();
        }

        private IEnumerable<SearchItem> FetchItems(SearchContext ctx, SearchProvider provider)
        {
            for (int i = 0; i < 10; i++)
            {
                string text = "Test Item" + i.ToString();
                yield return provider.CreateItem(ctx, text, text, null, null, null);
            }
        }
    }

On the last question:

I’m making an ecosystem of systems I use into a plugin for Unity. It uses assets as the main way to modularize game logic. Some these assets are graphs: Behavior Trees, State Machine, and Utility Theory graphs (I’ll probably only release BTs and SMs initially). I have a way to look for references to other assets, and to some int ids in these graphs. It makes things easier to debug at scale; there are so many modularization opportunities with these graphs that being able to pin point which element of which graph is referencing something is very useful.

I decided to remake my search system into a Search Provider for multiple reasons:

  • One of my goals is to make my stuff play well with the common Editor UX. Users are probably more familiar with the Search Window than with any custom UI I make. It does have some quirks and a couple of bugs, but it’s not so bad that it isn’t usable. I find it very useful myself as a normal user.

  • I can use the same filter words that other Unity providers use. So, for example, I can use “ref=” to allow users to search inside graphs at the same time they search in the Scene and in other assets.

  • It makes it very easy for things to scale with the fetch callbacks. I can provide delayed search results by using an IEnumerable for fetchItems, and then I can delay the results’ descriptions, labels, icons, etc.

  • The API is very extensive, and there’s a lot of documentation content. I found it relatively easy to use it. I may have used my own thing instead of this API if it wasn’t so easy to make something with it.

I’d also say that a bit of clean up could go a long way with the Search API. There are some bugs, like the ones I mentioned. Another one I’m remembering now is that dragging an item that supports dragging (e.g. a Scene result) when in List View mode, often triggers a "Starting multiple Drags. You can only start one drag at a time!" error.

There’s a good amount of things in the API that are no longer being used or that don’t do what is said in the docs. For example:

  • context.empty no longer returns true when there’s only a provider id in the search text.
  • The saveFilters param is no longer used in SearchService.ShowWindow.
  • There are exposed types that were clearly meant to be internal, or at least they should have a different name. For example, there’s an ObjectField that collides with UITK’s own ObjectField. That ObjectField in particular is kind of bothersome when writing custom UITK code for columns, or when triggering the Search API from other UITK elements.
  • There are more cases like these, I’m only writing some that I remember now.

All in all, though, this Search API and tools are awesome. Really useful, very nice idea. Congratulations to the team. I hope the higher ups at Unity can appreciate the importance of tools like these.

Thank you! :slight_smile:

EDIT
About solving the onDisable question at hand. By now, after learning a lot more while finishing my provider, I’m almost sure this is a bug on Unity’s side. I think I can survive without it being fixed. I’m already clearing my cache whenever I detect a change, either through Undo callbacks, asset postprocessor, or EditorApplication.projectChanged. In practice, I think cache cleaning is triggered enough for most use cases. If it can be fixed, or if there’s a work around, I’d still appreciate it, but it’s not blocking my development anymore.

Hi @oscarAbraham ,

Thanks for your feedback and answer. I am glad the framework we built for Search can be useful for tools developer.

As for the bugs: we will try our best to fix these in the coming months.

I tried your provider in my u6 build… and onDisable got called? I was using Unity 6000.0.29f
search_on_disable

I will try to tets with .30

If you are interested in more advance feature for search we have the search-extensions package:

This package contains a prototype Dependency Viewer.

The Wiki of this package also contains article highlighting more advance workflows and API:

I think the article describing SearchQuery and Table could be useful for you: https://github.com/Unity-Technologies/com.unity.search.extensions/wiki/Collection-Tool.

1 Like

I have tested with 6000.0.31f and onDisable is still called.

Can you explain the workflow you are doing that makes onDisable NOT called?

Like you see in my gif above, I open the search window through the global Search button and close the Window using the X button. Are you doing something else?

Thanks,

Seb

Thank you very much for your help. I really really appreciate it.

Oh no! I’ve just tested in a new empty project and it does work there. :frowning: There most be something in my project that’s preventing onDisable from running. I’ll try to find it and if I do I’ll share it. Do you have any recommendations on where to start looking?

EDIT
Spoke to soon. I was able to reproduce it in an empty project. It seems there is a combination of circumnstances that makes the bug happen. I’ll experiment a bit to find exactly what triggers it and share later.

Hi. Thanks again for your help. Here are the steps to reproduce the bug:

  1. Open the search window.
  2. Enable the Query Builder Mode.
  3. Click the + button to add a new query block.
  4. On the Select Search Area menu, select a search provider. It seems any of them will do.
  5. Close the window. “Disabled” isn’t printed to the console. If it’s printed for some reason, just open the Search window and close it again to trigger the bug.

NOTES:
“Disabled” is printed when the window is not open and there’s a Domain Reload.

A couple of times, I’ve been able to get a “Disabled” printed after closing the window even when the bug had been triggered. I think it involves changing the Provider in the Query Block, unfocusing the Unity Editor application, and maybe Domain Reload.

Except those two previous cases, most of the time, “Disable” won’t be printed when closing the Search Window after the bug is triggered. It seems nothing untriggers it other than closing and opening Unity.

EDIT
In case it helps, these are the providers and options I had enabled:

EDIT 2
I just saw the links to the Extensions and the Wiki. I think the Dependency Viewer is awesome; it helps a lot in big projects. I already had starred it on GitHub. The Wiki is useful too. Thank you.

I am able to repro. It seems if you remove the focus from the searchfield , on disable isn’t called. This is a bug. I will log it and ensure it is fixed. Thanks for the feedback.

1 Like

Oh! That makes a lot of sense. Thank you!