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. Voting for the Unity Awards are OPEN! We’re looking to celebrate creators across games, industry, film, and many more categories. Cast your vote now for all categories
    Dismiss Notice
  3. Dismiss Notice

Parent/Child Materials in Unity?

Discussion in 'Shaders' started by JakeFromBend, Dec 14, 2018.

  1. JakeFromBend

    JakeFromBend

    Joined:
    Jun 22, 2014
    Posts:
    6
    I'm fairly new to Unity, but I've been using UE4 for a long time.
    One of my favorite features from UE4 in regards to shaders is the ability to have materials (or as they're called in UE4, 'Material Instances') reference other materials, and not just shaders.

    Here's what that would look like:
    nested_materials.jpg

    The benefits of this type of setup are that you can more easily make 'global' parameter changes or even change the referenced shader, and have it propagate to dozens or hundreds of materials.

    I tried getting materials to reference other materials, but it doesn't look like that's supported. I couldn't find anything in the docs, either.

    Is this possible, or am I out of luck?
    -Jake
     
    Last edited: Dec 14, 2018
    Merman likes this.
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,230
    Unfortunately this isn't a feature that Unity has an equivalent of. It is one of the big features I miss from Unreal too.

    For people unfamiliar, a Material Instance is a normal asset, like a Material in Unity, with a list of properties. However instead of selecting a specific shader it has a parent Material asset. The Material Instance can be used to selectively override specific settings of the parent material asset. That parent material can even be another material instance, hence the chain.

    This kind of multi-level hierarchical chain overriding just isn't something that's common in Unity workflows. The closest equivalent in Unity would be to use Material Property Blocks, which are run-time material property overrides. They're limited to only modifying properties so you can't override keywords with them (Unity's equivalent to a Static Switch), and they're not assets or hierarchical, so they have to be managed with C# scripts to apply. I've done this in the past for a few situations, basically make the equivalent of a Material Instance in the form of a component script and two materials where the second material exists just to hold some data, and then have the component list of which properties to copy over.

    It'd be plausible to write a scriptable object that holds all of the override data, and even chain together, but I've just never bothered to go that far down that road. Having them all update when a parent changes would also be kind of ugly.
     
    JakeFromBend likes this.
  3. JakeFromBend

    JakeFromBend

    Joined:
    Jun 22, 2014
    Posts:
    6
    Thanks, this was my conclusion as well. I just figured i'd ask in case I was just missing something.
    Unfortunately, a run-time solution wouldn't be desirable, as i'd still want precompiled versions of the shaders but otherwise, that's a pretty workable solution.
     
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,230
    The shaders are still precomputed. The properties of a material are irrelevant to the computation of a shader. Apart from keywords, there's no way to set compile time constant values in a shader from the editor. It can only be set in the shader file itself.

    This is mostly how it works in Unreal too, btw. One big thing that Unity has over Unreal is that Keywords, which are essentially the equivalents to Unreal's Static Switches as mentioned above, can be changed at runtime. You can setup your shaders to always enable all possible combinations of certain keywords, or only compile them if used by a material, and additionally tell Unity to compile certain combinations regardless of if anything uses it or not in the content to allow for this switching to occur. That's what Shader Variant Collections are for.
     
    JakeFromBend likes this.
  5. JakeFromBend

    JakeFromBend

    Joined:
    Jun 22, 2014
    Posts:
    6
    Gotcha, thanks.
     
  6. Merman

    Merman

    Joined:
    Nov 16, 2014
    Posts:
    51
    @JakeFromBend I was actually trying to figure this out, too.

    What I tried was along the lines of:
    Code (CSharp):
    1. [SerializeField] private MeshRenderer meshRenderer;
    2. [SerializeField] private Color color;
    3.  
    4. void OnValidate()
    5. {
    6.      meshRenderer = GetComponent<MeshRenderer>();
    7.      meshRenderer.material.color = color;
    8. }

    It actually appeared to have the desired result: three different GameObjects in my scene were able to use different colored "instances" of the same material -- they were even automatically renamed "materialName (instance)". But Unity immediately started complaining about instantiating materials in Edit Mode resulting in leaks.
    Instantiating material due to calling renderer.material during edit mode. This will leak materials into the scene. You most likely want to use renderer.sharedMaterial instead.

    Trying this using MeshRenderer.sharedMaterial results in materials more accurately named "materialName (Clone)". But as @bgolus explains below, this is just a new material with copied properties (it will not be further influenced by or have any connection to the original material).

    (Unity definitely uses material instances "under the hood", so to speak. https://docs.unity3d.com/ScriptReference/Renderer-material.html explains that with little ambiguity. So perhaps the leak issue was just due to the fact that my fast experimental code didn't destroy or unload the instantiated materials.)
     
    Last edited: Dec 20, 2018
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,230
    Not really. There's an issue of terminology here. A material that shows "My Material (instance)" is just what they call a copy, not an "instance" in the way you might think coming from Unreal. It is functionally identical to:

    Material newMat = new Material(originalMat);
    newMat.name = originalMat.name + " (instance)";


    You're just making a new material that copies the settings of another at the time it's created. After that there's no tie back to the original material and no changes to the original are propagated. But, just as the editor complained, it does mean you're now creating a bunch of new objects at runtime that don't get cleaned up automatically by garbage collection. In other words they should be naming those materials "My Material (temporary copy)" as it's more accurately what they're doing. It is much better to use material property blocks to do these kinds of modifications as those won't make full copies of the material, do get cleaned up by garbage collection, and effectively keep the parenting aspect of UE's material instances.
     
    Merman likes this.
  8. Merman

    Merman

    Joined:
    Nov 16, 2014
    Posts:
    51
    I was returning to update my previous post after further experimentation revealed this. Clearly you don't need me to tell you that you're absolutely correct, haha!
     
  9. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,230
    I asked about this a few years ago as I was confused too. The short version is when they wrote the code they didn't really understand that "instance" meant something in this context in other applications. They just thought it as a synonym for clone or copy. ;)
     
  10. DEEnvironment

    DEEnvironment

    Joined:
    Dec 30, 2018
    Posts:
    436
    It been around 4 years for this post to get updated however HDRP 13x has something new
    o_O better late than never

    upload_2022-4-1_18-31-57.png

    upload_2022-4-1_18-33-11.png
     
  11. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    2,836
    Just FYI, it's not specific to HDRP.
     
    DEEnvironment likes this.
  12. DEEnvironment

    DEEnvironment

    Joined:
    Dec 30, 2018
    Posts:
    436
    i was looking around but have not found any documentation yet
    any hints on how we should use this correctly:)

    also do you know of any changes in shaders related or is this just the material system
     
  13. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    2,836
    I'll ask around :)

    Just materials, and Editor only.
     
    DEEnvironment likes this.
  14. aleksandrk

    aleksandrk

    Unity Technologies

    Joined:
    Jul 3, 2017
    Posts:
    2,836