Search Unity

SaveAsPrefabAsset returns null (even is successful)

Discussion in 'Prefabs' started by TheJimz, Nov 30, 2018.

  1. TheJimz

    TheJimz

    Joined:
    Jun 26, 2015
    Posts:
    50
    Unity 2018.3.0b11

    Having a problem with prefab creation, where SaveAsPrefabAsset() is successful but returns null. GetCorrespondingObjectFromSource() returns null. AssetDatabase.LoadAssetAtPath() returns null.

    However, the prefab is none the less successfully created. The problem is that I can't create the prefab, and then modify it with AddObjectToAsset() to save meshes, etc. to it.

    Posing a difficult problem in our asset pipeline, and seems to me it must be a bug. I'm making the call inside of PostProcessAllAssets(), and it seems the saved prefab is not being 'imported' until after my code exits, but it's too late then to update it properly.
     
    Airmouse likes this.
  2. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
    This is not a bug. When create prefabs inside import of other assets, the file is correctly saved, but the import is queued.
    This mean we can't return a valid reference to the asset as the asset does not exists in the assetdatabase.

    What is your use case for needing the new prefab directly in the post processor?
     
  3. TheJimz

    TheJimz

    Joined:
    Jun 26, 2015
    Posts:
    50
    We use the post-processing to detect and combine meshes within imported FBX model prefabs. We create a new prefab with the combined geometry. So I would like to create a new prefab, and then add the combined meshes to it. Seems a reasonable thing to do, as well it used to work in 2017 and prior. It needs to be an automatic generation and not a manually triggered one - would you have a suggestion as to how to go about doing this?
     
    Prodigga likes this.
  4. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    We've had similar workflows in our projects in the past. Definitely important!
     
    Airmouse likes this.
  5. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    639
  6. Prodigga

    Prodigga

    Joined:
    Apr 13, 2011
    Posts:
    1,123
    Edit:

    Deleted most of my post, I made up some example to demonstrate why this sucks, but the post Bellow mine does a better job!
     
    Last edited: Dec 3, 2018
    Airmouse likes this.
  7. TheJimz

    TheJimz

    Joined:
    Jun 26, 2015
    Posts:
    50
    I realize I can successfully create a prefab, that isn't the issue. I mentioned it's successfully created in my top post.

    How do I add a mesh to the prefab? Previously we attached the mesh to the prefab with AssetDatabase.AddObjectToAsset(), but we can no longer do that inside the import callback as you can no longer get a reference to it.

    So I'm curious what a proposed solution to the above would be. (adding a mesh to a newly created prefab created in the import callback)
     
    Last edited: Dec 3, 2018
    CardboardDude likes this.
  8. CardboardDude

    CardboardDude

    Joined:
    May 12, 2017
    Posts:
    1
    I too have the problem mentioned above by TheJimz. If anyone has a solution to it I would be grateful.
     
  9. TheJimz

    TheJimz

    Joined:
    Jun 26, 2015
    Posts:
    50
    My workaround is to create the prefab and basically exit out, letting it be imported which will trigger the postprocess callback again, recognize it's our recently created prefab and continue the initialization.
     
    Arkade and CardboardDude like this.
  10. nemerle

    nemerle

    Joined:
    Feb 20, 2019
    Posts:
    1
    I've encountered this issue as well while writing an importer for a scene format that uses its prefabs heavily:

    There, I build the source scene-graph (DAG) and count the number of times each internal node is referenced. Every node that has a number of references larger then 1 has to be turned into Unity-side prefab.

    The solution proposed by @SteenLund is of limited use in case of creation of a nested hierarchy of prefab assets during post-process/import phase.
     
  11. TonCol

    TonCol

    Joined:
    Jul 30, 2013
    Posts:
    3
    I have encountered this and ended up caching the path of the saved prefab and implementing a post asset import stage and patching up the references to the prefabs then.
     
  12. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,562
    I just faced this issue now myself. We have some editor code that creates a prefab on the fly and saves it to disk as part of our asset bundle build process.

    When calling SavePrefabAsAsset we're getting null, even though the prefab is indeed created and exists on disk.
     
  13. Arkade

    Arkade

    Joined:
    Oct 11, 2012
    Posts:
    655
    Hitting the same problem here too @SteenLund.
    Where can we vote to request this be changed? Went with this workaround suggested by @TheJimz -- thank you!

     
  14. mgear

    mgear

    Joined:
    Aug 3, 2010
    Posts:
    9,445
    ended up here from google, same issue..
    would be nice to have better alternative than having to go postprocess route..

    the old PrefabUtility.CreatePrefab() was working fine.. /cc @SteenLund
     
  15. THAMATRIX

    THAMATRIX

    Joined:
    Sep 6, 2018
    Posts:
    10
    Encountered the same problem in my project and I would want to ask Unity to please remove the GameObject return type and make it void. It is so missleading to return a GameObject reference that is always null.
     
    EAllin likes this.
  16. sviannay

    sviannay

    Joined:
    Feb 18, 2014
    Posts:
    4
    Don't know if it can help, but I had same issue, trying many workaround like the "delayed process" solution which worked, and in the end I realized I used to embed my creating prefabs process in a AssetDatabase.StartAssetEditing() / AssetDatabase.StopAssetEditing() block because without it's really slow.
    Removing it (StartAssetEditing()/StartAssetEditing()) solved the problem in my case, now PrefabUtility.SaveAsPrefabAsset() return prefab instance and not null anymore as expected.

    In fact, assetdatabase auto-refresh status was then disabled so it should explain why it returned null.