- Home /
Cycle through object materials on mouse click in C#
I have an object in my scene - a projection screen - that I need to cycle through different "slides" on a mouse click. I've tried working with a bunch of different examples I've come across, but it seems like the API update with Unity 5 (combined with my lack of experience) is throwing me for a loop. The chunk of code I've come up with seems like it should work, but when I run the game, I get bupkis other than the default material.
using UnityEngine;
using System.Collections;
public class SwapTextures : MonoBehaviour
{
public Material[] myMaterials;
int arrayPos = 0;
void updateMaterials ()
{
if (Input.GetMouseButtonDown (0)) {
arrayPos++;
arrayPos %= myMaterials.Length;
GetComponent<Renderer> ().material = myMaterials [arrayPos];
}
}
void Update ()
{
updateMaterials ();
}
}
Seems fine to me as well. What exactly happens when you click?
Absolutely nothin'. Here's what's in the Inspector:
I suspect that the problem lies with the $$anonymous$$eshRenderer, specifically that it has multiple materials, but you use Renderer.material in your code. Use Renderer.materials ins$$anonymous$$d:
void update$$anonymous$$aterials ()
{
if (Input.Get$$anonymous$$ouseButtonDown (0)) {
Renderer renderer = GetComponent<Renderer>();
for(int i = renderer.materials.Length - 1; i > 0; i--) {
renderer.materials[i] = my$$anonymous$$aterials [arrayPos];
}
}
}
We are using a reverse loop here just to be sure. A foreach loop won't work here because we try to change the elements in the array from inside the loop, and the reverse loop allows us to avoid any indexing problems (although this is more relevant when looping through a list and deleting elements)
Your Swap Textures script works fine. What type of shader are your Brocade x materials using? Does the shader type require a texture (such as Unlit/Texture), if so, do the materials have textures assigned to them?
Still nothin'. I copied the code exactly and replaced the old code with it and it still didn't do anything.
Answer by Key_Less · Jun 23, 2015 at 01:30 AM
I see you're using the same material multiple times within your 'MeshRenderer' component; more than one material should only be used here if your model requires multiple materials for rendering. There is no point iterating through the materials list if all materials are the same. Are you only changing one material, or will you eventually be using multiple materials for the 'Mesh1' model?
If you are only changing a single material, I would use your original code which works perfectly fine. However I would suggest using 'sharedMaterial' instead of 'material'.
If you're planning on changing all the materials, remember that all arrays in Unity return a copy, meaning that if you'd like to change the materials array you'll need to get a copy of the materials array, edit the copy, and then set the materials back to the object.
Here are a couple examples of what you could do:
1) If you're changing multiple materials:
using UnityEngine;
public class SwapTextures : MonoBehaviour
{
public Material[] MyMaterials;
private int arrayPos;
private Material[] modelMaterials;
void Start()
{
modelMaterials = GetComponent<MeshRenderer>().sharedMaterials;
}
private void UpdateMaterials()
{
if(Input.GetMouseButtonDown(0) && MyMaterials.Length > 0)
{
arrayPos++;
arrayPos %= MyMaterials.Length;
// If changing multiple materials...
for(var i = 0; i < modelMaterials.Length; i++)
{
modelMaterials[i] = MyMaterials[arrayPos];
}
GetComponent<MeshRenderer>().sharedMaterials = modelMaterials;
}
}
void Update()
{
UpdateMaterials();
}
}
2) If you're changing a single material:
using UnityEngine;
public class SwapTextures : MonoBehaviour
{
public Material[] MyMaterials;
private int arrayPos;
private void UpdateMaterials()
{
if(Input.GetMouseButtonDown(0) && MyMaterials.Length > 0)
{
arrayPos++;
arrayPos %= MyMaterials.Length;
GetComponent<MeshRenderer>().sharedMaterial = MyMaterials[arrayPos];
}
}
void Update()
{
UpdateMaterials();
}
}
That did it! Had to tweak one or two things (and then remember to turn the script back on after turning it off for debugging :P ) and it works!
Thank you, $$anonymous$$ey_Less, and everyone else for chi$$anonymous$$g in to help out. This is all immensely appreciated. :)