Identifying materials

Hi there!

When i was adding more buildings, I had the problem that for some buildings, the wrong material was colored. To identify which material should be set to the team colors, i added
image to TeamColorSetter.cs and dragged the Material “BuildingWhite” in on the buildings prefab. Also I updated HandleTeamColorUpdated and added a foreach loop to compare the current renderer’s materials against the new input. For the comparision I have to use renderer.sharedMaterial, as renderer.material is instantiated and will therefore always return false when compared with teamColorMaterial. SetColor on the other hand should not be applied to the sharedMaterial, but to the current material instance instead. My question is: How do i get the current material’s respective sharedMaterial / is there a more elegant way to achieve selective recoloring of defined material(s)?

image

This is working, but updates the shared material - not what I want to achieve:

image

Hi there, if I understand your question correctly, objects with shared materials actually don’t have their own instance of that material. Essentially for performance reasons they all reference the shared material, even during runtime. What you can do is create an instance of the material at runtime if you want to modify it.
To do this just declare a new material and set the material to it.

Material materialInstance = new Material(renderer.material);
renderer.material = materialInstance;

Hi there,

unfortunately this doesn’t solve the problem. Let’s assume the following:

I have a model which uses two materials: Material A and Material B.

In my script I want to change the base color of Material A only for this model, not for other models that use Material A.

Therefore my idea was to add an serialized input field of Type Material - let’s call it materialReference - and compare it with each of the renderers materials… basically:

image

The problem is, that material == materialReference ALWAYS returns false, even for the correct material. This only works for sharedMaterials, like in this example:

image

This code however would change the base color for every model that uses the specified shared material, which is not what i want.

What I needed was something like this:

image

Or basically any other way to identify whether or not the current material is the one I want to be changed.

You can try comparing the materials by name instead.
if(sharedMaterial.name == materialReference.name)
See if that helps?

sharedMaterial.name == materialReference.name surely returns true when its the same sharedMaterial. But again… comparing sharedMaterials with one another is not the problem here and it doesn’t really make sense to compare sharedMaterials’ names, when you can just directly compare the sharedMaterial instead and get the same result. The problem is that there appears to be no link between the material of a game object (which from my perspective is in fact an instance of the shared material (which seems to works like a prefab in this scenario) - the materials name also stronly hints towards it, see below) and it’s respective shared material - or at least I haven’t found one.

If you use material.name it will basically return $"{sharedMaterial.name} (Instance)". Hence you could compare material.name with $"{materialReference.name} (Instance)", but this seems like a really wacky workaround to me…

Well, once you have created an instance of a material, then they are no longer the same material in the eyes of Unity. Presumably the == comparison for a materials just looks at the object/memory reference. So it wouldn’t know if they are the same, that is why I suggested using the name instead.

I feel like a better way to do this, would just be to assign the material to the building from a script and set up all the references in advance. So instead of getting a reference to the prefab material, just get the reference to the exact renderers which materials you want recoloured. Do the same thing of making a SerializedField and drag in the renderer in the building prefab. Then at runtime you can pull the material from that renderer, create a new instance of the material, recolour it, then assign it back to it’s renderer.

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.

Privacy & Terms