Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

How on earth do you store extra data during OnPostprocessModel?

Discussion in 'Scripting' started by Kayamon, Sep 27, 2018.

  1. Kayamon

    Kayamon

    Joined:
    Sep 5, 2018
    Posts:
    5
    Hi,

    So I'm trying to extend the model import process so that my models have extra data stuck in there. What I really want is to write an OnPostprocessModel callback that analyses the model and sticks new procedurally-created sub-assets into the model along with the regular Mesh, Material, and AnimationClips you get. Or failing that, I'd like to attach a custom MonoBehaviour onto the model's prefab so I can put my data there instead.

    I've been banging my head against a wall all day trying to figure out how to make this work. It doesn't seem like any of the code out there on the web deals with this case.

    If I try attaching a custom MonoBehaviour to the prefab from inside OnPostprocessModel, it seems to import fine but when I then drop the object into the scene, my component has been replaced with the old "The associated script can not be loaded. Please fix any compile errors." (there are no compile errors btw). It works fine if I attach a builtin pre-existing component, but when attaching my own one it just won't load.

    What's weird is I can then drag/drop the script over it, and it springs into life. Except the data I filled in is missing, but then if you click 'Revert' it all suddenly appears.

    So that doesn't seem to work right. However the other option of storing my data as a custom sub-asset within the model doesn't work either. I just can't seem to find a way to actually make the new asset persist within the main asset. Here's the code I'm using for that:

    Code (CSharp):
    1.  public class MySuperModelProcessor : AssetPostprocessor
    2. {
    3.      void OnPostprocessModel(GameObject g)
    4.      {
    5.          if (assetPath == "Assets/test.blend") {
    6.              Debug.Log("Adding new objects into asset: " + assetPath);
    7.  
    8.              // Attempt to add an extra clip in there:          
    9.              AnimationClip clip = new AnimationClip();
    10.              clip.name = "My New Clip";
    11.            
    12.              context.AddObjectToAsset("my_new_clip_id", clip);
    13.              // ^^^^ This call seems like it should do the job,
    14.              //      but instead returns without error and does nothing.
    15.          }
    16.      }
    17. }
    It seems AddObjectToAsset is a pack of lies. The only working examples I've seen are when people use it to create a new asset file and save data there. That's not what I want to do -- I already have a model asset, I just want to attach extra data as it gets imported.

    Is this actually possible or am I just dreaming?
     
  2. teutonicus

    teutonicus

    Joined:
    Jul 4, 2012
    Posts:
    67
    Code (CSharp):
    1. void OnPostprocessModel(GameObject model)
    2. {
    3.     var rig = model.AddComponent<Rig>();
    4.     // setup etc.
    5.     EditorUtility.SetDirty(rig);
    6. }
    Either the documentation for how to do this stuff doesn't exist or I am terrible at searching for it. I went through a lot of messing around with assets not serializing correctly, editor crashing etc. until I came upon EditorUtility.SetDirty. I use the above pattern when creating custom AnimationClips in OnPostprocessModel as well, again calling SetDirty after I've created my custom asset and added an AnimationClip as a sub asset via AddObjectToAsset. I can't copy paste the code directly, but 1. edit/customise/create asset in OnPostprocess 2. call SetDirty when done is the pattern that works for me.
     
    Kayamon likes this.
  3. Kayamon

    Kayamon

    Joined:
    Sep 5, 2018
    Posts:
    5
    omg yes thank you, EditorUtility.SetDirty magically fixes it for attaching components. At least this way I can now stick my custom data in a MonoBehaviour and export that. Still no clue how you'd ever bundle in a custom ScriptableObject asset, but I'll make do.

    And no, you're absolutely right that there's no documentation for this stuff o_O
     
    teutonicus likes this.
  4. Totoro83y

    Totoro83y

    Joined:
    Sep 21, 2013
    Posts:
    21
    Hi, I'm trying to make this working too. My code is simply this one:

    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3.  
    4. public class ImportPostprocessor : AssetPostprocessor
    5. {
    6.     protected void OnPostprocessModel(GameObject g)
    7.     {
    8.         AnimationClip clip = new AnimationClip
    9.         {
    10.             name = "test"
    11.         };
    12.  
    13.         context.AddObjectToAsset("test_id", clip);
    14.         EditorUtility.SetDirty(clip);
    15.     }
    16. }
    And it doesn't seems to add anything importing the file. Someone had success in importing something like this? I can add the clip externally to the file, for sure, but I'd like to avoid it if I can.
     
    gustavolsson likes this.
  5. gustavolsson

    gustavolsson

    Joined:
    Jan 14, 2011
    Posts:
    339
    I'm trying to do the same thing... It seems like this only works for ScriptedImporters, not for AssetPostprocessors?
     
  6. fum1

    fum1

    Joined:
    Jul 5, 2017
    Posts:
    4
    I'm facing the same problem.
    Same with Unity 2019.4.2.
    I would like to hear the views of the people inside Unity Technologies.
     
    adamkvd and Hypnotoad0 like this.
  7. Hypnotoad0

    Hypnotoad0

    Joined:
    Jun 22, 2013
    Posts:
    40
    Yes. I'm also having trouble with this.
     
    adamkvd and fum1 like this.
  8. adamkvd

    adamkvd

    Joined:
    Nov 28, 2017
    Posts:
    4
    Is there any official update or explanation on this?

    I need to import a mesh and generate additional geometry (based on the imported one) as part of the import process.

    I can't go with a ScriptedImporter, because as far as I'm aware, there is no way to invoke a different importer as a pre-processing step for a custom import - but if there is no way to extend import results with additional data / objects, an AssetPostprocessor won't work either.

    Any ideas or insights would be appreciated!
     
    fum1 likes this.
  9. GamerXP

    GamerXP

    Joined:
    Mar 22, 2014
    Posts:
    74
    No updates to this issue? Only workaround I found so far is to completely replace data of one of the existing objects with data you need, but that create its own problems.