Help, cannot change reference of Renderer.material
I have fought with this for some time and done lots of googling yet i have failed to succeed in this. In my game the player can create alot of objects at runtime and i want him to be able to change what color the created objects are. Some could be blue, some red, etc. and i had it working in a way that it always created new instance of material, which later on now caused me quite a bottleneck on dynamic batching.
I have created a material/color storage class system and am able to save them there succesfully but i can't apply them to the objects Renderer.sharedMaterial for some reason (it doesn't change anything) and if i use Renderer.material it creates new instance. Most likely the problem here is my lack of understanding how the materials/renderer works. Any help appreciated.
Heres the code im running:
private void CreateObject()
{
if (!GetInput.cursorOverHud)
{
foreach (Transform t in Placeholders)
{
Transform o = UnityEngine.Object.Instantiate(t, t.position, t.rotation) as Transform;
foreach (Collider col in o.GetComponents<Collider>())
col.isTrigger = false;
o.gameObject.layer = 9;
o.GetComponent<Rigidbody>().isKinematic = false;
o.GetComponent<DynamicObject>().Set();
Renderer oRend = o.GetComponent<Renderer>();
Renderer tRend = t.GetComponent<Renderer>();
for (int i = 0; i < oRend.sharedMaterials.Length; i++)
{
// Nothing happens
oRend.sharedMaterials[i] = MatColStorage.GetMaterial(tRend, tRend.sharedMaterials[i].color, i);//mat[i];//tRend.sharedMaterials[i];
// But if i were to assign into 'oRend.materials[i]' i get lots of instantiated materials
}
}
}
}
And the storage class:
public static class MatColStorage
{
private class MaterialColor
{
private Material mat;
private Color col;
public Material material
{
get
{
return mat;
}
}
public Color color
{
get
{
return col;
}
}
public MaterialColor(Material material, Color color)
{
mat = material;
mat.color = color;
col = color;
}
}
private static List<MaterialColor> instantiatedMaterials = new List<MaterialColor>();
public static Material GetMaterial(Renderer rend, Color col, int whichMat)
{
foreach(MaterialColor matcol in instantiatedMaterials)
{
if(matcol.color == col)
{
return matcol.material;
}
}
Material refMat = new Material(rend.materials[whichMat]);
refMat.color = col;
instantiatedMaterials.Add(new MaterialColor(refMat, col));
return instantiatedMaterials[instantiatedMaterials.Count - 1].material;
}
}
Answer by Blue-Cut · Apr 22, 2016 at 10:02 PM
Hello,
This is not going to work :
oRend.sharedMaterials[i] = MatColStorage.GetMaterial(tRend, tRend.sharedMaterials[i].color, i);
Unfortunatly, I don't have the knowledge to explain you in detail why it's not working, but the fact is the the array sharedMaterials[] behaves like the properties you can't access directly. It's the same kind of not working case than :
// This is not working, you need to use a tmp vector
transform.position.x = myFloat;
So what you need to do is :
Material[] tmpMats = new Material[];
// you have your for loop here
tmpMats[i] = MatColStorage.GetMaterial(tRend, tRend.sharedMaterials[i].color, i);
oRend.sharedMaterials = tmpMats;
Whoa thank you so much! Darned debugger never even noted me about the fact that i cant do it, i even checked the UnityEngine.dll and i completely missed that it's an property.
Thank you again, horrible problem it was.