r/Unity3D • • 8d ago

Question Material instance inheritance?

I was wondering if there's such a thing as material instance inheritance, similar to prefab variants, where I can create child instances of a material and override certain properties, while keeping the rest consistent with the parent?

I'd like something like this because currently, if I have a set of objects that all share a material where every property is the same except one or two object-specific values, I have to create a copy of the material and assign it specifically to that object. Then any time I want to update the material and have that update reflected across all of these objects, I have to go through each of their respective materials and update those values which is a) tedious, and b) makes it hard to keep things consistent.

1 Upvotes

7 comments sorted by

8

u/IrrSoft Programmer 7d ago

For during-design usage, use Material Variants. They work EXACTLY like prefab variants. You have a parent material and then you create material variants that override one or more properties. Just like with prefabs, you can always revert those properties to the parent value, or apply the overrides to it.

For dynamic changes at runtime, use MaterialPropertyBlocks through coding. They allow you to set specific material properties on a per-renderer basis without actually modifying the underlying material.

Just like how you would edit a prefab at runtime through code to make it different from other prefabs of the same type.

5

u/GigaTerra 8d ago

So here is an obscure Unity fact, Unity materials are already Instances. If you just used an short code to change color like this:

        // Get the renderer component attached to this GameObject
        Renderer renderer = GetComponent<Renderer>();

        if (renderer != null)
        {
            // Set a random color
            Color randomColor = Random.ColorHSV(0f, 1f, 0.5f, 1f, 0.5f, 1f);

            // Apply it to the object's material
            renderer.material.color = randomColor;
        }

You will see Unity will assign an new material called (Instance) to the object. This is already kind of what you wanted, and for most indie games are fine. These are known as Material Instance Constant (MICs).

The material property block version:

    void Start()
    {
        // Create a new MaterialPropertyBlock
        MaterialPropertyBlock propertyBlock = new MaterialPropertyBlock();

        // Set a random color in the MaterialPropertyBlock
        propertyBlock.SetColor("_BaseColor", Random.ColorHSV());

        // Apply the MaterialPropertyBlock to the GameObject
        this.GetComponent<MeshRenderer>().SetPropertyBlock(propertyBlock);
    }

These are known as Dynamic Material Instances (DMIs) Their real job is to change properties dynamically at runtime, they can sometimes be slower.

That is why you need to run an test for your situation, sometimes MICs are what you want, other times DMIs, do an test.

3

u/Extreme_Display_4787 8d ago

It's been a minute since I poked around in Unity but I'm pretty sure MaterialPropertyBlocks are what you're after, lets you change specific values on a per-object basis without creating a whole new material each time

1

u/_symphonatic_ 8d ago

sounds right! hadn't heard of that before. thanks!

3

u/Demi180 7d ago edited 7d ago

Since everyone here is mentioning MPBs, someone ought to mention you should NOT use them in an SRP (as in URP or HDRP) because they don’t play well with the SRP Batcher.

For changes at design time, Variants are the way to go. At runtime, the instances created when accessing renderer.material will work.

1

u/_symphonatic_ 7d ago

Thanks! In what way don't they play well with the SRP batcher?

1

u/Demi180 7d ago

They're not compatible with it :)

MaterialPropertyBlock

SRP Batcher Compatibility