- Home /
Loop through all materials in scene and change them
Is there a way to access the materials in a scene at runtime, and reassign them?
Answer by Jean-Fabre · May 04, 2011 at 06:29 AM
Hi,
There is much better built in alternative.
Bounce from this page for other types of similar features.
If you are looking exchanging different materials etc etc, then you'll have to do it manually, and I would recommend doing a reusable component for it using GetComponentsInChildren(); to retrieve all renderer of that game Object and its childrens, then you can store material references, exchange them at will etc etc. I do that for example, when I need to hide parts of an assembly, I have a transparent shader that I swap at runtime.
If you need a more exhaustive description of such component, say so, and I'll wrap up something.
[EDIT] here is a component to do just that:
using UnityEngine; using System.Collections;
public class MaterialSwitcher : MonoBehaviour {
public Material switchMaterial;
private Hashtable _matList = new Hashtable();
private Renderer[] _renderers;
private bool switched;
/// <summary>
/// Record all material of the gameobject and its children
/// </summary>
void Start () {
_renderers= GetComponentsInChildren<Renderer>();
foreach( Renderer _renderer in _renderers){
_matList.Add(_renderer,_renderer.material);
}
}
/// <summary>
/// just for testing
/// </summary>
public void Update(){
if (Input.anyKeyDown){
ToggleMaterial();
}
}
/// <summary>
/// Toggle between the switch material and the default.
/// </summary>
public void ToggleMaterial(){
switched = !switched;
if (switched){
SwitchMaterial();
}else{
ResetMaterial();
}
}
/// <summary>
/// Revert to the default material
/// </summary>
public void ResetMaterial(){
switched = false;
foreach( Renderer _renderer in _renderers){
_renderer.material = _matList[_renderer] as Material;
}
}
/// <summary>
/// Switch to the predefined switchMaterial
/// </summary>
public void SwitchMaterial(){
switched = true;
SetMaterial(switchMaterial);
}
/// <summary>
/// If you want to assign an arbitrary material
/// </summary>
/// <param name="mat">
/// A <see cref="Material"/>
/// </param>
public void SetMaterial(Material mat){
switched = true;
if (mat==null){
Debug.LogWarning("no Material defined to set on GameObject: "+name);
return;
}
foreach( Renderer _renderer in _renderers){
_renderer.material = mat;
}
}
}
Bye,
Jean
Answer by Bryan 4 · May 03, 2011 at 09:43 PM
you would need the game objects you want to change, then you can set the gameObject.renderer.material or gameObject.renderer.materials[] for multiple materials if necessary.
Slow way (not wise to use it every frame), but it works: GameObject[] objects = (GameObject[]).FindObjectsOfType(typeof(GameObject)); Works just for active objects, of course :) Or you could get all LineRenderers: FindObjectsOfType(typeof(LineRenderer))
This one is not documented... but should be better to use in this case: FindSceneObjectsOfType(typeof(GameObject)) http://www.google.com/search?hl=en&q=FindSceneObjectsOfType
Answer by David St-Hilaire · May 04, 2011 at 12:51 PM
I agree with Jean, I think that for each object that you want to switch materials, you should add a component on that object that will perform the switch. This component can look maybe like:
public Material NewMaterial;
public void Awake() { renderer.material = NewMaterial; }
If you need to have a more complex logic to choose between multiple materials, you can add it to this class and change the material to the desired one. This more distributed approach seems more in the Unity way of doing things, which I like alot ;p
-- David
Your answer
Follow this Question
Related Questions
Load data from file, if scene changed, fails to load location 0 Answers
Changing material during runtime 1 Answer
GameObject references runtime script in scene file. Unsure whats wrong 2 Answers
How can I load 3d models(.obj, .fbx) dynamically in to unity scene after building it to WebGL ? 1 Answer
Create scenes at runtime 2 Answers