- Home /
Changing an object's material script C#
I am new to Unity and I am having some trouble. I am creating a role playing scene where there are 2 quads and each has a separate 2d image of a character. At a certain point in the script I change a variable and when this changes I want the material to change one quad at a time. I tried using this script and put my alternateMaterial in the Resources folder:
public Material alternateMaterial;
renderer.material = alternateMaterial;
and while this does not give me an error, it just simply does not work. What am I doing wrong? Is there a way to assign the object multiple materials and just swap which material is shown?
Thanks in advance!
Did you assign alternate$$anonymous$$aterial in the Inspector? Did you set a breakpoint to ensure that this line gets executed? What is 'not work'? Can you edit and post more code?
if you Debug.Log(renderer.material.name) both before, and after the this assignment
Debug.Log("before assignment, current $$anonymous$$at " + renderer.material.name + " alt $$anonymous$$at "+ alternate$$anonymous$$aterial.name);
renderer.material = alternate$$anonymous$$aterial;
Debug.Log("after assignment, current $$anonymous$$at " + renderer.material.name);
do both of them display, and does the name actually display?
is alternate$$anonymous$$aterial actually different then the
I know the line gets executed because I have a log statement right above it. I dont know if I can assign alternate$$anonymous$$aterial in the Inspector because I already have a material on the object
do both of them display, and does the name actually display?
No it does not. I get an error: UnassignedReferenceException: The variable alternate$$anonymous$$aterial of 'ChangeScript' has not been assigned.
as long as alternate$$anonymous$$aterial is public, and Unity knows how to serialize it can be assigned in the inspector (on the script)
if you are getting an UnassignedReferenceException then that means you have not assigned it. (wonder why it didn't just through NullReferenceException, but this is more telling)
Answer by gardian06 · Sep 18, 2013 at 09:15 PM
if I want to assign potentially multiple different materials to the same object, or even different materials to different objects. instead of having to track down each and every object that needs to have their materials switched out (tedium in large scenes). I create a static MaterialRepo class that can be called, and used to assign to any object. then I just have a script on the object that needs its material to change just reference the MaterialRepo.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class MaterialRepo : MonoBehaviour {
public List<Material> mats;
public static MaterialRepo inst;
// Use this for initialization
public void Awake () { if(inst == null){ inst = this; } }
// Update is called once per frame public void Update () { }
public Material GetMat(string _name){
if(mats != null && mats.Count > 0 && _name != null && _name != ""){
foreach(Material mat in mats){ if(mat.name == _name){ return mat; } }
}
return null;
}
public Material GetMat(int _index){
if(mats != null && mats.Count > 0 && _index >= 0 && _index < mats.Count){
return mats[_index];
}
return null;
}
public Texture GetTex(string _name){
if(mats != null && mats.Count > 0 && _name != null && _name != ""){
foreach(Material mat in mats){ if(mat.name == _name){ return mat.mainTexture; } }
}
return null;
}
public Texture GetTex(int _index){
if(mats != null && mats.Count > 0 && _index >= 0 && _index < mats.Count){
return mats[_index].mainTexture;
}
return null;
}
}
then when I want an object to get a material from the repo while maintaining a reference to their previous one I can just have it do so by:
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(Renderer))]
public class MatChangeExample : MonoBehaviour {
public int desiredMat;
public bool useMat1;
private Renderer _rend;
private Material mat0;
private Material mat1;
// Use this for initialization
void Start () {
_rend = renderer;
mat0 = _rend.material;
mat1 = MaterialRepo.inst.GetMat( desiredMat );
}
// Update is called once per frame
void Update () {
if(useMat1 == true && _rend.material != mat1){
_rend.material = mat1;
}else if(useMat1 == false && _rend.material != mat0){
_rend.material = mat0;
}
}
}
Awesome job gardian06!
I modified the "swapper" script so that it can support multiple materials applied to the mesh. For multiple swaps simply add multiple times this script. I'm not a coder so surely it would be possible to pack multiple swaps in a single script but...
public class ThermalSwap : $$anonymous$$onoBehaviour {
public int index;//refers to the index of the multiple materials aplied to the mesh. 1,2,3....
public int desired$$anonymous$$at;//Index of the material in the $$anonymous$$aterial Repo 0,1,2...
public bool use$$anonymous$$at1;
private $$anonymous$$aterial[] mat_reset;
private $$anonymous$$aterial [] mat0; // position of existing material to swap
private $$anonymous$$aterial mat1;//thermal material
// Use this for initialization
void Start () {
mat_reset = renderer.materials;
mat0 = renderer.materials ;
mat1 = $$anonymous$$aterialRepo.inst.Get$$anonymous$$at( desired$$anonymous$$at );
}
// Update is called once per frame
void Update () {
//for (var i = index; i > renderer.materials.Length; i=index-1 )
// index = i;
if(use$$anonymous$$at1 == true ){
//mat0[i] = mat0;
mat0[index] = mat1;
renderer.materials = mat0;
}else if(use$$anonymous$$at1 == false){
mat0[index] = mat_reset [index];
renderer.materials = mat0;
}
}
}
nope sorry it wont work swapping multiple materials. Yes it works with a mesh with multiple materials but if you duplicate script only one swap will be performed.
I'll make an array of public materials and not consider the neat $$anonymous$$aterial Repo.
Anyway probably one might find usefull the previous script.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
Rainbow Material Script Not properly running 1 Answer
Change skybox color via script? 0 Answers