Question & Test Sharing: Does modifying material at runtime can potentially cause memory leak?

Recently I have been assigned to optimize our project and came across this ‘common knowledge’ that I’ve never heard of:

  • Modify a renderer.material at runtime will create a new material
  • Not all draw calls to meshes can be batch dynamically

Can’t say I am proud of myself but it is a good thing to learn it now then never. So I decided to test out how much memory costs there will be if I modify material at runtime(which our project currently is doing, a lot!)

Test: Does modifying materials at runtime costs memory leak?
Unity Version: Unity 2019.1.2f1

Description:

A simple scene where a little fish model(details below) prefab, with rigidbody2D and box collider2Das well as a looping swim animation attached , is instantiated 300 times in the center of the scene with a default orthograpic camera.

At runtime, I will be changing the color of the fish through its SkinMeshRenderer’s material every 3 seconds. The variable here is the approach that I changed it.

Project A will be changing the color by directly changing the color field of the material.
Project B will be switching the material of the SkinMeshRenderer’s material field with a dragged in material array where the only differences between them is the color.

Process:
I ran both projects at the same pc for about 12 hours and here is the result:
A: 6654976--760543--ResultA.png
B:6654976--760546--ResultB.png
Also a peek into system task monitor: (A up, B bottom)

Summary:
Try to avoid modifying material at runtime for it will create new material instances.

Reference:

It’s not a “memory leak” in the sense you’re acting like it is because this is the intended behaviour. The alternative would be for every single renderer using the same material to create an instance of that material, which would be a major amount of overhead and potentially send draw calls through the roof.

If you want to change the same material, use sharedMaterial property.

If you want to use the same material but affect different properties in it, use instancing and MaterialPropertyBlock: