Texture2D to Plane: Array Index is Out of Range
Hi, thank you for looking at my post.
GOAL:
I'm attempting to write a C# script which creates a random plane via mesh, then applies a random texture from a folder to the shaded Material. The ultimate goal is to have no repeating textures (textures are only used once for one plane), but I'm not necessarily worried about repeats right now. This C# script generates a plane after dropping it on an Empty Game Object and pressing Play.
ISSUE:
I've read dozens of posts and similar questions, read scripting guides etc., and cannot figure out how to apply a random texture to a randomly generated plane, even after consulting an intermediate coder (I'm a beginner). As of right now I THINK I have all of the textures loading into the Texture2D[] Array (Lines 81, 96-98) but I'm now getting this issue despite adding .Length-1:
IndexOutOfRangeException: Array index is out of range.
RotationPositionScaleTexture.Start () (at Assets/Complete.cs:97)
CODE:
using UnityEngine;
using System.Collections;
using UnityEditor;
using System.Linq;
// CREATE PLANE
public class CreatePlaneMesh : MonoBehaviour {
public float width = 50f;
public float height = 50f;
void Start () {
MeshFilter mf = GetComponent<MeshFilter>();
Mesh mesh = new Mesh();
mf.mesh = mesh;
//Vertices
Vector3[] vertices = new Vector3[4];
{
vertices[0] = new Vector3(0f,0f,0f);
vertices[1] = new Vector3(width,0f,0f);
vertices[2] = new Vector3(0f,height,0f);
vertices[3] = new Vector3(width,height,0f);
};
//Triangles
int[] tri = new int[3];
tri[0] = 0;
tri[1] = 2;
tri[2] = 1;
//Normals
Vector3[] normals = new Vector3[4];
normals[0] = -Vector3.forward;
normals[1] = -Vector3.forward;
normals[2] = -Vector3.forward;
normals[3] = -Vector3.forward;
//UVs
Vector2[] uv = new Vector2[4];
uv[0] = new Vector2(0, 0);
uv[1] = new Vector2(1, 0);
uv[2] = new Vector2(0, 1);
uv[2] = new Vector2(1, 1);
//Assign Arrays
mesh.vertices = vertices;
mesh.triangles = tri;
mesh.normals = normals;
mesh.uv = uv;
}
}
public class Complete : MonoBehaviour {
void Start() {
gameObject.AddComponent<MeshRenderer> ();
gameObject.AddComponent<MeshFilter> ();
gameObject.AddComponent <CreatePlaneMesh>();
gameObject.AddComponent <RotationPositionScaleTexture> ();
}
}
// RANDOM ROTATION, POSITION, SCALE AND TEXTURE
public class RotationPositionScaleTexture : MonoBehaviour {
public Texture2D[] textures;
int texCount;
void Start () {
float x = Random.Range (-10f, 10f);
float y = Random.Range (-10f, 10f);
float z = Random.Range (-10f, 10f);
gameObject.transform.rotation = Random.rotation;
gameObject.transform.position = new Vector3(x,y,z);
gameObject.transform.localScale = new Vector3 (x, y, z);
Material eleven = Resources.Load ("eleven", typeof(Material)) as Material;
gameObject.GetComponent<Renderer> ().material = eleven;
Texture2D[] textures = (Resources.LoadAll ("Assets/Resources/Textures", typeof(Texture2D))).Cast<Texture2D> ().ToArray ();
Texture2D texture = textures[Random.Range (0,textures.Length-1)];
gameObject.GetComponent<Renderer>().material.mainTexture = texture;
}
}
SCREENSHOT:
http://i59.tinypic.com/260bzf9.png
You can see that for some reason the plane is black (not the usual magenta?) and not selecting any textures on Start(), even though they are in the correct Resources directory.
IDEAS:
Am I failing to apply textures to the mesh.UVs? Not sure. Please know that I wouldn't post this if I hadn't spent over 20 hours trying to figure this out by consulting the Scripting guide and other posts multiple times. New to coding and this way of thinking.
I appreciate your help!
Possible reason for the error: You have declared the (array) variable textures two times (global: line 79 and local: line 93).
Answer by Yword · Oct 16, 2015 at 10:53 AM
The path parameter in Resources.LoadAll is relative to the Resources folder, so
Resources.LoadAll("Assets/Resources/Textures")
should be changed to
Resources.LoadAll("Textures")
Besides, if the parameters for Random.Range are integer, then it will returns a random integer number between min [inclusive] and max [exclusive], so
Random.Range(0, textures.Length - 1)
should be changed to
Random.Range(0, textures.Length)
Thank you for your help! It's now working beautifully, I'd been working the code with alternative methods so much that I missed the basics of the Resources.LoadAll, and your answer in conjunction with @saschandroid solved the problem.
Finished code for anyone trying to do similar things:
using UnityEngine;
using System.Collections;
using System.Linq;
// Plane generation hidden due to comment length.
public class Complete : $$anonymous$$onoBehaviour {
// Use this for initialization
void Start() {
gameObject.AddComponent<$$anonymous$$eshRenderer> ();
gameObject.AddComponent<$$anonymous$$eshFilter> ();
gameObject.AddComponent <CreatePlane$$anonymous$$esh> ();
gameObject.AddComponent <RotationPositionScaleTexture> ();
gameObject.AddComponent<ScreenShot> ();
}
}
// RANDO$$anonymous$$ ROTATION AND TEXTURE
public class RotationPositionScaleTexture : $$anonymous$$onoBehaviour {
public Texture2D[]s;
int texCount;
void Start () {
float x = Random.Range (-10f, 10f);
float y = Random.Range (-10f, 10f);
float z = Random.Range (-10f, 10f);
float a = Random.Range (1f, 10f);
float b = Random.Range (1f, 1f);
float c = Random.Range (1f, 100f);
gameObject.transform.rotation = Random.rotation;
gameObject.transform.position = new Vector3(x,y,z);
gameObject.transform.localScale = new Vector3 (a, b, c);
$$anonymous$$aterial eleven = Resources.Load ("eleven", typeof($$anonymous$$aterial)) as $$anonymous$$aterial;
gameObject.GetComponent<Renderer> ().material = eleven;
Texture2D[] textures = (Resources.LoadAll ("Textures", typeof(Texture2D))).Cast<Texture2D> ().ToArray ();
Texture2D texture = textures[Random.Range (0,textures.Length)];
gameObject.GetComponent<Renderer>().material.mainTexture = texture;
}
}
public class ScreenShot : $$anonymous$$onoBehaviour {
int added = 0;
void Update(){
if (Input.Get$$anonymous$$eyDown ($$anonymous$$eyCode.Space))
added++;
Application.CaptureScreenshot ((System.IO.Path.Combine(
System.Environment.GetFolderPath( System.Environment.SpecialFolder.Desktop ),
"screenshot" + added + ".png") ), 4);
}
}
Your answer
Follow this Question
Related Questions
How to load a folder of textures automatically to an array of Raw Images? 2 Answers
Assign an image as a texture to a mesh 1 Answer
How to create a mesh for 2D maps with transparent parts, which is generated by software? 0 Answers
Is it possible to draw primitive shapes on to a Texture2D? 1 Answer
Creating an Array that can be accessed by a Random.Range c# 1 Answer