Search Unity

Question Discrepancy between AssetDatabase.GetDependencies and results of ExportPackage()

Discussion in 'Asset Database' started by g4ma, Jun 13, 2022.

  1. g4ma

    g4ma

    Joined:
    Dec 18, 2018
    Posts:
    32
    Hello!

    I am seeing differences between what I get from AssetDatabase.GetDependencies() and the list of files that an interactive ExportPackage() offers me when invoking both on the same asset and I am not sure why.
    This is not about .cs files which I now ExportPackage() is quite conservative about, but regular assets dependencies.

    More details:
    All of my model files (FBX) come with a sibling custom descriptor file that I am using to reference e.g. various textures that I can apply at runtime to this model.
    So the dependency graph looks like this:
    Model -> descriptor file -> textures etc.

    I have a model AssetPostprocessor that correctly set up the dependency from the model to the descriptor file, and my custom descriptor file importer correctly set up the dependencies to the textures.
    And it seems to be working fine with the regular package export that indeed offers me to export the following items:
    - Model.fbx
    - descriptorFile
    - texture0
    - texture1
    etc.


    However calling AssetDatabase.GetDependencies() on the same model asset will only yield
    - Model.fbx
    - A lit shader (I suppose the default one listed by the FBX)


    So, my two questions:
    - what is causing this discrepancy?
    - how can I retrieve the actual dependencies as show by ExportPackage?

    Thanks!
     
  2. Unity_Javier

    Unity_Javier

    Unity Technologies

    Joined:
    Mar 7, 2018
    Posts:
    190
    Hi @g4ma ,
    Looking through the source of both Export and AssetDatabase.GetDependencies, I can see that Export uses AssetDatabase.GetDependencies (under the hood).

    The only potential difference could be the recursive parameter inside of AssetDatabase.GetDependencies as that will go through the dependency chain and get the guids of an assets' dependencies.

    This "include dependencies" value gets used internally by GetDependencies:
    upload_2022-6-21_14-20-36.png

    Would you mind trying:
    Code (CSharp):
    1. AssetDatabase.GetDependencies(assetPath, true);
    and see if that fixes the discrepancy?
     

    Attached Files:

  3. g4ma

    g4ma

    Joined:
    Dec 18, 2018
    Posts:
    32
    Thanks for your answer!

    By using "ExportPackage()" I can see with or without the "include dependencies" tickbox that indeed my descriptor file is being pulled or not.

    However changing the boolean to AssetDatabase.GetDependencies() does not change anything (I had it set to recursive already).

    Which led me to believe there was some difference in the behaviour of both methods. What could it come from?
     
  4. g4ma

    g4ma

    Joined:
    Dec 18, 2018
    Posts:
    32
    Investigating a bit more, the only workaround I could find was this: relying on an AssetPostProcessor, in a OnPostprocessModel() I added a custom MonoBehaviour on the GameObject and made sure to have it reference my descriptor file as a property field :

    Code (CSharp):
    1. class DescriptorData : ScriptableObject { [...] }
    2.  
    3. class DummyScript : MonoBehaviour
    4. {
    5.   DescriptorData DummyDependency;
    6. }
    7.  
    8.  public class Postprocessor : AssetPostprocessor
    9. {
    10.     void OnPostprocessModel(GameObject g)
    11.     {
    12.         string descriptorFilePath = FindDescriptorFile();
    13.         DescriptorData descriptorData = GetDataFrom(descriptorFilePath);
    14.         DummyScript cpnt = g.AddComponent<DummyScript>();
    15.         cpnt.DummyDependency = descriptorData;
    16.     }
    17. }
    18.  
    Then both functions yields the same result and the dependency chain I am expecting.
     
  5. Unity_Javier

    Unity_Javier

    Unity Technologies

    Joined:
    Mar 7, 2018
    Posts:
    190
    That's interesting, that it almost depends when during import you setup the dependency.

    We have this API:
    AssetImportContext.DependsOnSourceAsset
    AssetPostprocessor's have an AssetImportContext field (context) available (though I believe it may not be widely known, or obvious tbh).

    Could you please try doing this inside either the postprocessor, or in your actual code, if you're not doing so already:

    Code (CSharp):
    1. string descriptorFilePath = FindDescriptorFile();
    2. context.DependsOnSourceAsset(descriptorFilePath);
    And see if it works?
     
  6. g4ma

    g4ma

    Joined:
    Dec 18, 2018
    Posts:
    32
    Yes, this is what we do already. To be precise we do it like this:

    Code (CSharp):
    1. GUID guid = AssetDatabase.GUIDFromAssetPath(FindDescriptorFilepath());
    2. if (!guid.Empty())
    3. {
    4.     context.DependsOnSourceAsset(guid);
    5. }
     
  7. jdrewsen

    jdrewsen

    Unity Technologies

    Joined:
    Mar 28, 2011
    Posts:
    204
    Note that AssetDatabase.GetDependencies returns assets being referenced (a runtime dependency) whereas calling context.DependsOnSourceAsset(guid); will setup an import-time dependency. Difference between these two kinds of dependencies are:
    Import time dependency: Registered in the asset database to decide if an asset should be reimported because a dependency has changed.
    Runtime dependency: Anything the asset needs to be available at runtime for it to work property. E.g. assets that are referenced through a member field.
     
  8. g4ma

    g4ma

    Joined:
    Dec 18, 2018
    Posts:
    32
    That's interesting, thanks for this! It looks like some dependencies were indeed incorrectly setup.

    However I don't really get how ExportPackage() could only be based on GetDependencies() if the latter only returns runtime dependencies.
    To me exporting an asset as a package would require pulling its import time dependencies - if it did not, the exported asset would not be viable once reimported in e.g. another project. And indeed the behaviour I see with ExportPackage() shows that all import time dependencies are correctly listed.

    So getting back to the original question: given an asset how can I get its import time dependencies rather than only its runtime dependencies? Is there an API for this?
     
  9. jdrewsen

    jdrewsen

    Unity Technologies

    Joined:
    Mar 28, 2011
    Posts:
    204
    Correct... ExportPackage() uses GetDependencies() and also collects import time dependencies. Unfortunately the import time dependencies are only exposed as internal and not public API. We should probably change that. But as a work around until then you can use c# reflection to call the internal functions. The functions are
    Code (CSharp):
    1. string[] AssetDatabase.GetSourceAssetImportDependenciesAsGUIDs(string path)
    2. string[] AssetDatabase.GetImportedAssetImportDependenciesAsGUIDs(string path)
     
    kingmax_res likes this.
  10. g4ma

    g4ma

    Joined:
    Dec 18, 2018
    Posts:
    32
    That's perfect, thanks!
    I should have had a look at the AssetDatabase bindings, I would probably have seen those.

    Is there a formal process to get these exposed? My use case (getting import time dependencies) is pretty common in the context of assets pipeline development.
     
  11. unity_chris

    unity_chris

    Unity Technologies

    Joined:
    Dec 23, 2015
    Posts:
    18
  12. g4ma

    g4ma

    Joined:
    Dec 18, 2018
    Posts:
    32
    Nice, thanks again!