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

Question How to set material from metadata with no custom inspector?

Discussion in 'General Graphics' started by rod_lopez, May 17, 2023.

  1. rod_lopez

    rod_lopez

    Joined:
    Aug 10, 2017
    Posts:
    18
    Hi there!
    I have this not-so-odd situation where we have artists working on a DCC (Max or Blender at this point) and exporting an object (in .fbx format). Now, .fbx native materials don't hold the right data for our shaders, so most material data arrives in embedded metadata. I can parse that and push it to a material; so far so good.

    The tricky bit is the keywords. The way I have implemented the "setting shader keywords" is at the custom inspector. So in the OnGUI of the shader's custom inspector I check if a certain int is 0 or 1 to set or reset a keyword, say "SPECULAR_FROM_DIFFUSE_ALPHA".
    Of course, if the inspector doesn't show, the OnGUI doesn't run, so I can import the object, parse the metadata, set it, and still get the wrong result (until I show the inspector, when the OnGUI kicks in sets the keywords)

    The way we work with most materials is through asset bundles that get loaded at run-time (so no editor) and, in any case, we would want to batch convert materials anyway. No yeah, no editor or inspector needed.

    One possible solution would be to take away the code that iterates through property values and sets the keywords away from the OnGUI, kiiinda what Unity does in the Lit inspector.
    The way Unity does it is by setting the keywords from a static function of the custom inspector UI, so calling that on-demand would work.
    Oddly enough Unity does this on editor-only code, so running this code for loading in player mode, say loading an AssetBundle, (and again, assuming the material data comes from the metadata) would not work either <-the editor code wouldn't be compiled into the player.

    Am I alone coming across this issue? Frankly, the fact that the material inspector's GUI has to be visible for the material to have the right keywords set seems somewhat insane to me. Having a different call that's in Editor mode is better, but not ideal either.
    I can do something Unity'ish but that could be called from non-editor code; so, take metadata, put into material, and send material to the function that fixes things like keywords, same function I would call from the custom inspector. That seems reasonable to me, if a bit off the beaten path.

    Anybody came up with this before? Ideas?

    Thanks!
     
  2. c0d3_m0nk3y

    c0d3_m0nk3y

    Joined:
    Oct 21, 2021
    Posts:
    516
    Usually, you would do something like this in an Asset Pre- or Post-Processor:
    https://docs.unity3d.com/ScriptReference/AssetPostprocessor.html

    However, that's editor only. Without an editor, you'd have to do it after loading the asset.

    I'm afraid, I'm not entirely following what the problem is. Maybe somebody else can give you a better answer.
     
  3. rod_lopez

    rod_lopez

    Joined:
    Aug 10, 2017
    Posts:
    18
    Maybe that was a bit convoluted of an explanation. The problem is about creating materials in run-time.

    If you load meta-data at run-time (to create a material with it) you won't be able to trivially re-use the behavior on a custom inspector (e.g. to set things like keywords). Unity has an override-able function that set things up in the Lit shader (SetupMaterialKeywordsAndPassInternal) but that belongs to an editor-only class (the one that does the custom inspector for the Lit itself) so I can't trigger that behaviour in non-editor modes.
    Right now my solution is to break my custom inpector in editor and non-editor codebases, but it feels less than elegant.