- Home /
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.
Answer by CgShady · Aug 08, 2012 at 10:27 PM
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 :
assign the material to an object (say the first you want to have an individual look)
reference the assigned material (putting it in a List for example)
assign the referenced material to any other object that is supposed to
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!!
Answer by Jerc · Aug 07, 2012 at 08:01 AM
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.
I really must be missing something here.
I tried using : GameObject.renderer.material as Procedural$$anonymous$$aterial;
All I get is 3 materials using the same procedural material textures.
I want to "duplicate" a procedural material. In other words, I want to duplicate the generated textures as well. Say I have a procedural material that has a property called "sbs_color", I want to create several duplicates, each with a different colour.
Is that possible at all ?
Thanks
I am really interested in how you get this to work too. Please reply if you work something out :)
I can't reply more than once to my question, so here's some code sample to help you.
// Assigning $$anonymous$$aterial to a Dummy Game Object for Instancing
GameObject _tmp$$anonymous$$aterialHolder = new GameObject ("_tmp$$anonymous$$aterialHolder");
_tmp$$anonymous$$aterialHolder.AddComponent<$$anonymous$$eshRenderer> ();
_tmp$$anonymous$$aterialHolder.renderer.material = renderer.material;
_procedural$$anonymous$$aterialInstance = _tmp$$anonymous$$aterialHolder.renderer.material as Procedural$$anonymous$$aterial;
// Forcing $$anonymous$$aterials to be different by changing a procedural property
Color _tmpColor = new Color (Random.Range (0.1F, 1.0F), Random.Range (0.1F, 1.0F), Random.Range (0.1F, 1.0F), 1.0F);
if (_procedural$$anonymous$$aterialInstance.HasProceduralProperty ("Color"))
{
_procedural$$anonymous$$aterialInstance.SetProceduralColor ("Color", _tmpColor);
}
_procedural$$anonymous$$aterialInstance.RebuildTexturesImmediately ();
// Setting Filter $$anonymous$$odes and Aniso Levels
_procedural$$anonymous$$aterialInstance.GetTexture("_$$anonymous$$ainTex").filter$$anonymous$$ode = Filter$$anonymous$$ode.Trilinear;
_procedural$$anonymous$$aterialInstance.GetTexture("_$$anonymous$$ainTex").anisoLevel = 5;
_procedural$$anonymous$$aterialInstance.GetTexture("_Bump$$anonymous$$ap").filter$$anonymous$$ode = Filter$$anonymous$$ode.Trilinear;
_procedural$$anonymous$$aterialInstance.GetTexture("_Bump$$anonymous$$ap").anisoLevel = 5;
// TODO : $$anonymous$$ake sure textures are set to RAW
// Assigning $$anonymous$$aterial to Surfaces
otherObject.renderer.material = _procedural$$anonymous$$aterialInstance;
Hope this helps
what do you mean Instantiate should not be used with procedural material? Can you explain more
It seems it is implemented like this. Instantiate will throw you an error "IsFlagEnabled(Procedural$$anonymous$$aterial::Flag_Clone) || m_Pinged$$anonymous$$aterial==NULL || m_Pinged$$anonymous$$aterial==material" Source: https://forum.allegorithmic.com/index.php?topic=260.msg2359#msg2359
Your answer
Follow this Question
Related Questions
Why does my substance not generate all my maps properly? 1 Answer
Substance - How do you set the random seed of procedural material at runtime 0 Answers
How can i find the SBSAR(substance designer) parent of a Procedural Material? 0 Answers
How can I use Substance materials in Unity? 2 Answers
Substance question 2 Answers