Hei,
I expected this to be an easy question but I couldn’t find a solution so far. I want to add a material to an object (a net) and remove it later by script. As the materials are an array, I’m clueless here.
Hei,
I expected this to be an easy question but I couldn’t find a solution so far. I want to add a material to an object (a net) and remove it later by script. As the materials are an array, I’m clueless here.
You need to get a reference to the GameObject’s Renderer component. From there you can simply set the Renderer’s material property to whatever you please.
Thank you for your answer but I want to add, not change.
There’s also a property to set materials as an array.
If you have an object with multiple Materials, that ALSO implies that the mesh has multiple submeshes.
Each Material in the .materials array corresponds to a submesh, so just adding a material to an object isn’t likely to do much.
If you think you still want to, you need to:
.materials property all at once.You can NOT simply assign one element of the .materials array. You must at least pluck the whole thing out, change it, then also put it back. The reason: accessing it causes Unity to make you a copy.
EDIT: The same goes for .material: that returns a copy (as per the docs). You can copy it out, change it, but you MUST assign it back in.
Thank you for your answer. I feared that.
After going through all that and taking all possibilities into account, I made this decision for my project:
That didn’t work out that well. In the end I used @Kurt-Dekker s method:
public void SetAdditionalMaterial(Material newMaterial)
{
if (additionalMaterialApplied)
{
Debug.LogError("Tried to add additional material even though it was already added on " + name);
return;
}
Material[] materialsArray = new Material[(this.GetComponent<Renderer>().materials.Length +1)];
this.GetComponent<Renderer>().materials.CopyTo(materialsArray,0);
materialsArray[materialsArray.Length - 1] = newMaterial;
this.GetComponent<Renderer>().materials = materialsArray;
additionalMaterialApplied = true;
}
public void ClearAdditionalMaterial()
{
if (!additionalMaterialApplied)
{
Debug.LogError("Tried to delete additional material even though none was added before on " + name);
return;
}
Material[] materialsArray = new Material[(this.GetComponent<Renderer>().materials.Length - 1)];
for (int i = 0; i < this.GetComponent<Renderer>().materials.Length - 1; i++)
{
materialsArray[i] = this.GetComponent<Renderer>().materials[i];
}
this.GetComponent<Renderer>().materials = materialsArray;
}
It’s working as intended but giving me a warning, like @Kurt-Dekker said:
“This renderer has more materials than the Mesh has submeshes” and so on. Makes me feel I will run into trouble. How could I achieve
Read my post above again. If an object has X submeshes (that means something VERY specific in the Unity context), then it has X materials. You can’t just add and remove materials in that list without ALSO adding and removing submeshes, which requires you to procedurally modify the geometry.
Maybe it would be better if you explained what effect you’re trying to do here (crude drawings are also helpful for good communications), because it does not seem like the approach chosen is likely to get you joy.
And I fear you are right.
I want to draw a net on an Object like this. This is how it works right now with above posted script:

In this case a drone is using a cheap cargonet to catch an Asteroid. What material is put on top can differ (material, age,…) and has to come from the interacting GameObject.
I would do this: make two objects side by side in your 3D modeling program, one of them the asteroid, one of them the net.
That way as you are making them you can align them just so.
Once imported and placed into a prefab, just turn the net on and off when you capture it!
That way if in the future you want a crazy complicated animated net with cloth strings and an animation driving it so it looks like it flaps in the breeze on reentry to a planet or when your ships thrusters are pointed at it, you just make that animation and control that animation, and everything else works.
If you did the above in Blender3D, just go into edit mode, select the cargonet, press P to partition it and don’t move it and everything else can pretty much work. I would parent them both to an empty axes object if I was in Blender.
I love that!
Thing is, I’m using objects from the Assetstore only. But you inspired me to just duplicate the object, resized it (*1.001) and still do the same. What do you think about it?
I LOVE IT! In fact, I’m fairly sure I’ve done that approach myself somewhere but I can’t recall when.
The only concern I can see is that 1.001 might not be enough and you will get Z-fighting flickering, especially once the object is farther from the camera. But if this is mostly a 2D game, maybe just find the scale you need?
You could also leave it the same size and move it towards the camera some larger amount. The cargo netting on the far side won’t render anyway (depending on shader / material) since the far side polys are pointed away…
But scaling might be cool because the net will look like it has some thickness at the very edges of the rock.
What about just making a copy of the surface texture, painting the mesh on it, and then swap the texture out and call it a day? I dunno if that would look as nice and even without a lot of texture fiddling, but it might look okay…
Great idea but in my special case not possible. I need the material to be exchangable and I can’t tell yet what I will need in future. It’s also 3D. I just found out that *1.01 looks best in my setting and I’ll start with that and see where this goes.
Thank you very much for your help!
functions:
...
[Header("Additional Material handling")]
private MeshRenderer additionalMaterialContainer;
...
virtual public void OnDisable()
{
if (additionalMaterialContainer.gameObject.activeSelf) ClearAdditionalMaterial();
}
...
public void SetAdditionalMaterial(Material newMaterial)
{
if (additionalMaterialContainer==null)
{
Debug.LogError("Tried to add additional material but no additionalMaterialContainer is configured on " + name);
return;
}
if (additionalMaterialContainer.gameObject.activeSelf)
{
Debug.LogError("Tried to add additional material even though it was already added on " + name);
return;
}
additionalMaterialContainer.GetComponent<Renderer>().material=newMaterial;
additionalMaterialContainer.gameObject.SetActive(true);
}
public void ClearAdditionalMaterial()
{
if (additionalMaterialContainer == null)
{
Debug.LogError("Tried to delete additional material but no additionalMaterialContainer is configured on " + name);
return;
}
if (!additionalMaterialContainer.gameObject.activeSelf)
{
Debug.LogError("Tried to delete additional material even though none was added before on " + name);
return;
}
additionalMaterialContainer.GetComponent<Renderer>().material = null;
additionalMaterialContainer.gameObject.SetActive(false);
}