1

I have created a simple color swap shader, and then a material from it. Now, I would like to see the effect in action in Edit Mode.

However, I receive the following error:

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.

I do not want to update the sharedMaterial, because I want to be able to set different colors for different game objects, and using that property would change the value in the base material, which I do not want.

What do I need to change to address the error, please?

Here's my script:

[ExecuteInEditMode]
public class ColorSwap : MonoBehaviour
{
    [SerializeField] private Color color;

    private SpriteRenderer spriteRenderer;

    private void Awake()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();
    }

    void Start()
    {
        spriteRenderer.material.SetColor("color", color);
    }
}
2
  • Why can't you test in play mode? This is a warning so you can ignore it. Commented Sep 2, 2024 at 12:08
  • I can, but I don't want to, as I am looking for convenience. It is not a warning, it is an error. And it does trigger the instantiation of materials, so causes problems. Commented Sep 2, 2024 at 13:50

1 Answer 1

3

renderer.material is interesting. The first time you reference it, Unity will create a copy of the first sharedMaterial on the renderer, and then replace that first sharedMaterial with its own instance.

If the material is used by any other renderers, this will clone the shared material and start using it from now on.

...

This function automatically instantiates the materials and makes them unique to this renderer. It is your responsibility to destroy the materials when the game object is being destroyed

Unity - Scripting API: Render.material

The creation of that copy is why you get a warning- you now have a new Material asset, and that asset has to be saved somewhere, otherwise how would the scene reference it?


Instead of creating new materials, you can try using a MaterialPropertyBlock. This lets you modify a material parameter for a single renderer, without the need to create new materials:

[ExecuteInEditMode]
public class ColorSwap : MonoBehaviour
{
    [SerializeField] private Color color;

    private SpriteRenderer spriteRenderer;
    private MaterialPropertyBlock mpb = new();

    private void Awake()
    {
        spriteRenderer = GetComponent<SpriteRenderer>();
         
        // Copy the existing material properties into the MaterialPropertyBlock
        // to ensure that the default values are properly handled
        spriteRenderer.GetPropertyBlock(mpb);
    }

    void Start()
    {
        // Set the "color" property for this object.
        mpb.SetColor("color", color);
        spriteRenderer.SetPropertyBlock(mpb);
    }
}

If you want to remove these MaterialPropertyBlock overrides, just pass null as the argument to SetPropertyBlock. Optionally, you can use GetPropertyBlock again to make sure the default values are up-to-date:

void ClearMaterial() {
    // Clears any overrides
    spriteRenderer.SetPropertyBlock(null);

    // Put the defaults back into "mpb"
    // Note: ??= is OK since MaterialPropertyBlock does not inherit from UnityEngine.Object 
    spriteRenderer.GetPropertyBlock(mpb ??= new());
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you! Please could you update your answer to also include how the material can be reset to its original state, i.e. how to remove the color again? At the moment, I use spriteRenderer.SetPropertyBlock(new MaterialPropertyBlock()); for that purpose. Is that correct?
To reset, you just have to pass null as the argument to SetPropertyBlock: "To disable any of per-Renderer or per-Material overrides, pass null as the property’s argument."

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.