Coroutine in ScriptedImporter?

It doesn’t appear that you can currently use a coroutine in a ScriptedImporter, so I am a bit unsure how to go about doing what I am trying to do.

I have a ScriptedImporter which during its processing may kick off the import of other external assets. It currently does this like so:

AssetDatabase.ImportAsset(path, ImportAssetOptions.ForceUpdate);

This works fine, with one major caveat, and that is that the asset appears to be imported by AssetDatabase async so the ScriptedImporter doesn’t stop and wait for it, which messes everything else up.

I thought I might just use a coroutine to wait until all required external assets were verified to be loaded, but like I said it doesn’t appear you can use a coroutine in ScriptedImporter.

Any thoughts?

Since ScriptedImporter is in the UnityEditor.Experimental.AssetImporters namespace, I’m not sure that coroutines would work well (if at all) there.

You might need to use EditorApplication.update and IEnumerator.MoveNext() to manually iterate through your coroutines.

That sounds like basically implementing my own version of coroutines which sounds super complicated.

Ok maybe not as complicated as I thought. After a bit of searching I figured out how to do what you suggest. Sadly it appears that the editor isn’t content on waiting though and as soon as execution moves to the “coroutine” the editor errors out about not having received the expected asset yet :frowning:

So I appear to be somewhat screwed and there is probably a different way to approach this but I’m unsure what that is. If only I could just tell the AssetDatabase to do the load synchronously :frowning:

Not really. If all you want is the logical notion of separating flow and keeping local “task state” going, and you don’t care about timing, etc. the way that the Unity “real” coroutines do, what @BlackPete suggested is really trivial, and essentially amounts to just having a master list of “stuff I am working on” that contains pumpable coroutines, and then you just keep pumping them until the list is exhausted. Certain of your coroutines could add additional tasks to the main list of things to run, which just keep going and keep the whole process running, all in the same frame.

And by “pumping” them, I mean running their MoveNext methods until they’re exhausted, as you would with iterating any enumerator.

Unity’s implementation of coroutines is part of MonoBehaviour. They’re entirely dependent on inheriting that class.

Did you try AssetDatabase.Refresh(ImportAssetOptions.ForceSyncronousImport) ?

I did use Refesh but didn’t notice that flag, but that had an annoying side effect in that it caused the ScriptedImpoter that called refresh to get called again. So essentially the import would happen twice for every asset. While not neccesarily a huge problem, it was a issue with very large assets that can take upwards of 10 minutes or more to import just once, let alone be called twice.

Now that I am made aware of that flag though I will try it again. Maybe its just a matter of a bug report to Unity to fix the issue of the importer getting called twice.

Thanks!

I’m not 100% certain, but I believe to workaround’ed this or a similar issue by delaying the AssetDatabase.Refresh call one update, as shown below.

EditorApplication.delayCall += delegate()
{
    AssetDatabase.Refresh(ImportAssetOptions.ForceSyncronousImport);
};

However, I don’t know whether this works in your case.

Wouldn’t that no longer be synchronous at that point? The import wouldn’t happen until the next tick and the calling code will continue on. So this doesn’t really solve anything unless I am misunderstanding.

I have managed to get this working with a sort of two pass import process, where I make an initial skeleton asset to keep Unity happy, then schedule a follow up pass using EditorApplication.delayCall that then takes the external assets and hooks them up.

1 Like

Today I learned!