Set Random Material from folder
Hello, I'm making an underground system made of Capsules and I have around 100 Materials all originate from Sprites texture. Eventually, there would be around 500 Capsules to cover a large area.
My goal, Give a different random Material from a folder to each Capsules at Start-Runtime.
-All the Materials are in a Folder named FirstLayerMaterials that is itself in a Folder named UnderGround.
-All the Capsules have the Script UnderGroundCapsules.
-All the Capsules are children of a GameObject named UnderGroundBlocks with the Script UnderGroundBlocks.
-All the Capsules have a tag "NotDurt".
-All the Capsules Shader must be set to Sprites/Default.
In C# in the Parent UnderGroundBlocks (Script UnderGroundBlocks) that holds the Capsules.
public class UnderGroundBlocks : MonoBehaviour {
GameObject[] Durts;
void Start(){
Material[] materials = (Material[]) Resources.LoadAll("FirstLayerMaterials");
Durts = GameObject.FindGameObjectsWithTag("NotDurt");
foreach(GameObject capsule in Durts){
capsule.GetComponent<Renderer>().material = materials[Random.Range(0, 100)];
}
}
}
My problem: Its giving an Error: InvalidCastException: Cannot cast from source type to destination type. UnderGroundBlocks.Start () (at Assets/WorldObject/UnderGound/UnderGroundBlocks.cs:13)
Thank you
Answer by wibble82 · Dec 23, 2015 at 12:28 PM
Hi
To answer for certain, I'd need to know which line 'line 13' is (i.e. the line the error refers to).
I suspect it is this line:
Material[] materials = (Material[]) Resources.LoadAll("FirstLayerMaterials");
The documentation seems to imply this is fine, but I'm fairly certain it isn't, as Resources.LoadAll won't necessarily return an array of materials. In fact I thought it would return a simple array of objects, possibly unless you actually specify a type as the 2nd parameter of Resource.LoadAll.
You could try:
Material[] materials = (Material[]) Resources.LoadAll("FirstLayerMaterials", typeof(Material));
From the docs that looks like it might work, though I've not tried it.
Or if not, this should certainly work:
void Start()
{
//allow Resource.LoadAll to just return a list of objects (filtered to only have materials in)
Object[] materials = Resources.LoadAll("FirstLayerMaterials", typeof(Material));
//get our 'Durts' and iterate over each one
Durts = GameObject.FindGameObjectsWithTag("NotDurt");
foreach(GameObject capsule in Durts)
{
//set material, adding a static cast to the Material type
capsule.GetComponent<Renderer>().material = (Material)materials[Random.Range(0, 100)];
}
}
Though finally, to be on the safe side, use the materials array length instead of '100' in the random:
capsule.GetComponent<Renderer>().material = (Material)materials[Random.Range(0, materials.Length)];
Hope that helps
-Chris
Answer by Fdudka · Dec 23, 2015 at 08:04 PM
Thank you Chris, yeah that was the line 13... Almost works, now its saying :
IndexOutOfRangeException: Array index is out of range. UnderGroundBlocks.Start () (at Assets/WorldObject/UnderGound/UnderGroundBlocks.cs:15)
line 15 is : capsule.GetComponent().material = (Material)materials[Random.Range(0, materials.Length)];
FirstLayer$$anonymous$$aterial folder was not in Resources folder....
Thank you and $$anonymous$$erry Christmas!!
Answer by zoppytevo · Aug 14, 2020 at 02:44 PM
How do I make the material change once every 3 seconds or more?