Hello !
I’m making a tool where I have to import a custom package from Github, and I need a call back when it’s completed in editor.
For that I use as recommend by the doc the AssetDatabase.ImportPackage callback, more precisely AssetDatabase.importPackageCompleted .
Here is the function where I declare the callbacks:
void Download()
{
AssetDatabase.importPackageCompleted += ImportCompleted;
AssetDatabase.importPackageCancelled += ImportCancelled;
AssetDatabase.importPackageFailed += ImportCallBackFailed;
AssetDatabase.importPackageStarted += ImportStarted;
AssetDatabase.ImportPackage(path, true);
}
And here the functions called by the callbacks:
static void ImportCompleted(string packageName)
{
Debug.Log ("Completed " + packageName);
AssetDatabase.importPackageCompleted -= ImportCompleted;
}
static void ImportCancelled(string packageName)
{
Debug.Log ("Cancelled " + packageName);
AssetDatabase.importPackageCancelled -= ImportCancelled;
}
static void ImportCallBackFailed(string packageName, string _error)
{
Debug.Log ("Failed " + packageName);
AssetDatabase.importPackageFailed -= ImportCallBackFailed;
}
static void ImportStarted(string packageName)
{
Debug.Log ("Started " + packageName);
AssetDatabase.importPackageStarted -= ImportStarted;
}
The only callback that works is the ImportStarted one.
Any idea?
PsyKaw
August 6, 2018, 3:08pm
2
Hello !
I try to put an AssetDatabase.Refresh (before and after by the way ^^) but it doesn’t work.
Oh btw, the issue tracker is put as fixed but no version is precise.
It doesn’t say fixed. It says by design which means that’s how it’s supposed to work.
The callbacks are removed only if a script recompile happens. Users are inclined to (re)register for the callback during the [InitializeOnLoad] attribute of scripts so that they can assure they receive the callback. It’s too risky otherwise to make the callback twice as it breaks backwards compatibility. Because the scripts are recompiled, we also can’t guarantee the callback function will still exist after the recompile, so we can’t store the delegates and then reset them after the recompile. As such, this feature will remain as designed with no changes.
1 Like
The AssetDatabase.importPackageCancelled does not reimport or recompile and it’s not being called. Is there a specific way to receive those calls? @karl_jones
If it’s not being called then it sounds like a bug. Can you please send a bug report?
Neither the AssetDatabase.importPackageCompleted and AssetDatabase.importCallBackFailed.
That was part of the original question. Or maybe there is something I don’t understand…
@karl_jones do we need to post three bug report or just 1 ?
@Martin_Gonzalez Did you send a bug report? If yes, could you share a link to the issue tracker?
Did you manage to make the other callbacks (Completed, Started, Failed) work? @Martin_Gonzalez
I didn’t use other evenst, I just wanted that one because my idea was to delete the file after import is completed.
As I see others wondering about receiving complete callback, will add some info. I receive complete callback. What I did: added log in static constructor to see when my class, waiting for callback is recreated. It is recreated for example, if assembly in which it resides is being recompiled. It may happen, if you import package which contain code. Note that. To save state between recompiles, you can write to file or use PlayerPrefs. I suggest you start from logging, like I did:
[InitializeOnLoad]
public class PackageRegistrar : AssetPostprocessor
{
static PackageRegistrar()
{
Debug.Log("PackageRegistrar: s_ctor");
AssetDatabase.importPackageStarted += OnImportPackageStarted;
AssetDatabase.importPackageCompleted += OnImportPackageCompleted;
}
public static void OnPostprocessAllAssets(
string[] importedAssets
, string[] deleted
, string[] movedAssets
, string[] movedFrom)
{
LogIfAny("importedAssets", importedAssets);
LogIfAny("deleted", deleted);
LogIfAny("movedAssets", movedAssets);
LogIfAny("movedFrom", movedFrom);
}
private static void OnImportPackageStarted(string packagename)
{
Debug.Log($"PackageRegistrar: OnImportPackageStarted({packagename})");
}
private static void OnImportPackageCompleted(string packagename)
{
Debug.Log($"PackageRegistrar: OnImportPackageCompleted({packagename})");
}
}
The output is:
PackageRegistrar: PackageRegistrar: OnImportPackageStarted(external-dependency-manager-latest)
PackageRegistrar: PackageRegistrar: s_ctor // so, it is recompiled in-between
PackageRegistrar: PackageRegistrar: OnImportPackageCompleted(external-dependency-manager-latest)
2 Likes
Deepscorn:
As I see others wondering about receiving complete callback, will add some info. I receive complete callback. What I did: added log in static constructor to see when my class, waiting for callback is recreated. It is recreated for example, if assembly in which it resides is being recompiled. It may happen, if you import package which contain code. Note that. To save state between recompiles, you can write to file or use PlayerPrefs. I suggest you start from logging, like I did:
[InitializeOnLoad]
public class PackageRegistrar : AssetPostprocessor
{
static PackageRegistrar()
{
Debug.Log("PackageRegistrar: s_ctor");
AssetDatabase.importPackageStarted += OnImportPackageStarted;
AssetDatabase.importPackageCompleted += OnImportPackageCompleted;
}
public static void OnPostprocessAllAssets(
string[] importedAssets
, string[] deleted
, string[] movedAssets
, string[] movedFrom)
{
LogIfAny("importedAssets", importedAssets);
LogIfAny("deleted", deleted);
LogIfAny("movedAssets", movedAssets);
LogIfAny("movedFrom", movedFrom);
}
private static void OnImportPackageStarted(string packagename)
{
Debug.Log($"PackageRegistrar: OnImportPackageStarted({packagename})");
}
private static void OnImportPackageCompleted(string packagename)
{
Debug.Log($"PackageRegistrar: OnImportPackageCompleted({packagename})");
}
}
The output is:
PackageRegistrar: PackageRegistrar: OnImportPackageStarted(external-dependency-manager-latest)
PackageRegistrar: PackageRegistrar: s_ctor // so, it is recompiled in-between
PackageRegistrar: PackageRegistrar: OnImportPackageCompleted(external-dependency-manager-latest)
Thank you. You are right about the recompilation thing that I ignored. So basically if the unitypackage contains any script file or assembly definition that will trigger the recompilation process, the callback function delegate will be cleared. Therefore, the delegate registration needs to take place after the recompiling. What Ive done is to put the delegate registration in a OnInitializeLoad class.
Just found out you have done the same thing. And it is very nice to use EditorPrefs store the state.