Cloning Substance (Procedural Material) at Runtime

Ok, I have many different surfaces (renderers) that I want to dynamically create procedural materials for.

What I’m doing now :

I have a reference material :

public ProceduralMaterial _substanceReference;

I have a table of procedural materials :

public ProceduralMaterial [] _materials;

Then for each of them I want to create a clone that I can change independently :

_materials[_index] = Object.Instantiate(_substanceReference) as ProceduralMaterial;

Now, if I change the property of one :

if (_material.HasProceduralProperty("myColor"))
{
 _material.SetProceduralColor ("myColor", _color);
 _material.RebuildTexturesImmediately();
}

It changes them all. It seems to be changing the original and not the clone.

I must be missing something here…

Thanks for your help.

Hi,

I figured it out, and will share my finding here.

I had a material (not procedural) reference, which I was tweaking before I would apply it to other objects.
I found that applying the material to an object “creates” the instance I was looking for.

So the proper process is :

  1. assign the material to an object (say the first you want to have an
    individual look)
  2. reference the assigned material
    (putting it in a List for example)
  3. assign the referenced material to any other object that is supposed to
  4. share the same material tweak the reference as you like

I was trying to instantiate the material before I would assign it.
It now works as I want, with pretty good performances.

Thanks!!

You can instantiate substances at runtime using renderer.material instead of renderer.Sharedmaterial, Instanciate should not be used with procedural materials.

ProceduralMaterial Instance = GameObject.renderer.material as ProceduralMaterial;

This will instanciate dynamically a new copy “Instance” of the procedural material applied to GameObject.