new Mesh() works outside of array, but not in array. Huh?

I’m attempting something that should be straightforward but unity has been doing a large number of really nonsensical things and I’m beginning to lose my mind. This takes the cake:
I’m trying to change the properties of a mesh (i’m trying to shear it). I store the sheared mesh inside a newly created Mesh variable. In the first script, I use Mesh name = new Mesh(). In the second, I use Mesh name = {new Mesh()}. The first one works. The second one gives an error, “Submesh index out of bounds”. The array/singular is the ONLY change. ???
I really need this to be an array. Any help would be appreciated because I don’t know where to go from here.

The problem is that you create a new mesh inside a FieldInitializer of your class. FieldInitializer are called even before the constructor of the class runs. Unity creates component classes on a seperate loading thread. From there you can’t access any Unity API. This includes creating other objects derived from UnityEngine.Object.

You should do the creation of your meshes in Start() which is actually called on the main thread.

Mesh[] newGraphicMeshes = new Mesh[8]; // you can create the array here

void Start()
    for(int i = 0; i < newGraphicMeshes.Length; i++)
        newGraphicMeshes *= new Mesh(); // but create your meshes here.*

// …
ExecuteInEditMode is not ment to be used for pure editor functionality. It’s ment for runtime script which have some effect at runtime that wouldn’t be seen in the editor otherwise. For example things that manually render objects in OnRenderObject. If you want to extend the editor you should either implement a custom inspector (like Unity did for the Terrain class), or create a seperate EditorWindow.
However we know not enough about how exactly you want to use that script to suggest any alternatives.

Are you sure about this? I think your suggestion will solve my problem, however Start() does not seem to run in the editor. I have asked the script to do a debug.log in start(), and I don’t see any results of this.
Edit: I did more testing; Start() runs when the scene is loaded or play is pushed. OnEnable() runs when the script component is enabled, first added, or recompiled. OnEnable is the one i want. This is the information i needed. Thank you!

@wibble82 Thanks for replying, i appreciate it.

I’ve done a bit more testing and determined that neither approach really ‘works’ in the traditional sense, and this singular vs array thing might be a symptom of a larger problem i’m having. I’ll explain what i’m trying to do. This is going to get weird.

The code I am using is this:

using UnityEngine;
using System.Collections;

public class RoadSegment : MonoBehaviour {

	[Header("Segment Components")]
	public Transform[] connectors;
	public GameObject[] graphicObjects;
	public Mesh[] graphicMeshes;
	public GameObject[] collisionObjects;
	public Mesh[] collisionMeshes;
	[Header("Material Selection")]
	public Material[] materials;
	[Header("Segment Transforms")]
	public float grade1;
	public float grade2;
	public float grade3;
	public float grade4;
	public enum gradeTypes { flat, up, down };
	public gradeTypes grade1Type;
	public gradeTypes grade2Type;
	public gradeTypes grade3Type;
	public gradeTypes grade4Type; 

	Mesh[] newGraphicMeshes = {new Mesh(), new Mesh(), new Mesh(), new Mesh(), new Mesh(), new Mesh(), new Mesh(), new Mesh()}; //I explain this line in my spiel below
	Mesh newCollisionMesh = new Mesh();
	Mesh target = new Mesh();

	void Start() {
		if (Application.isPlaying) {

	void Update() {
		if (graphicObjects.Length != graphicMeshes.Length) {
			Debug.LogError("Road Segment " + gameObject +": The number of graphicObjects and graphicMeshes must be the same. " +
				"Each graphicMesh represents the mesh used in the corresponding graphicObject. Taken together, they represent all the different meshes used on the object.");		}
		if (collisionObjects.Length != collisionMeshes.Length) {
			Debug.LogError("Road Segment " + gameObject +": The number of collisionObjects and collisionMeshes must be the same. ");		}
		if (graphicObjects.Length > 10) {
			Debug.LogError("Road Segment " + gameObject +": At this time, a maximum of 10 objects are supported in one road segment.");		}

		//graphicMeshes[0] = a reference to the original mesh file that i want to base my changes on.
		//graphicObjects[0] = a reference to the gameobject that i want to display the modified mesh.
		MeshFilter mf = graphicObjects[0].GetComponent<MeshFilter>();
		Mesh source = graphicMeshes[0];
		target.vertices = source.vertices;
		for(int i = 0; i < source.subMeshCount; ++i) {
			target.SetTriangles(source.GetTriangles(i), i);
		} //i am doing this with a for loop because a straight target.subMeshCount = source.subMeshCount causes unity to aneurysm. 
		target.tangents = source.tangents;
		target.uv = source.uv;
		target.uv2 = source.uv2;

		Vector3[] vertices = target.vertices;
		int j = 0;	float distance;
		while (j < vertices.Length) {
			distance = graphicObjects[0].transform.localPosition.y - vertices[j].y;
			vertices[j] += Vector3.forward * (distance * grade1); 
		mf.sharedMesh = target;
		mf.sharedMesh.vertices = vertices;

		//TransformGraphicMesh(0); <- my intention is to turn this one-off script using 'target' into an iterating function. This is what i wanted the array for.
		/*for (int k = 0; k < graphicObjects.Length-1; k++) {
			Debug.Log("k is "+k);

    void OnDrawGizmos()
		for (int i = 0; i < connectors.Length; ++i) {
            Gizmos.DrawWireSphere(connectors*.position, 1.0f);*

Gizmos.DrawRay(connectors.position, connectors_.forward2);

* void TransformGraphicMesh(int n) {*
* //the iterating version of the above code would go here.*

* }*
I know, it’s completely disgusting. I’ll explain.

This script is intended for a road builder in unity’s editor, and it runs at editor time. I want to allow each road segment to have the mesh transformed using the properties grade1, grade2 etc. This will make slopes. The meshes are instanced for each prefab to allow this to be set differently for different instances of the same road segment prefab.
Doing this requires changing the sharedMesh of the prefab. I obviously don’t want to change the original file, or the files of other meshes, so I instantiate a new copy of the original mesh and use that instead. The best and easiest way to do this is targetMeshFilter.sharedMesh = (Mesh)Instantiate.sourceMeshFilter.sharedMesh. If I do this in the update script, I generate thousands upon thousands of new meshes and cause a memory leak, and that’s no good; so instead I must make the new variable in the class declaration, where it only happens once, and is re-used. Of course, I can’t do that best and easiest method - I have to settle for creating a new mesh called target, and then assigning it all the properties of the old mesh. This took me hours to figure out.
So it seems straight forward, right? Just assign verts, tris, tangents, uvs, etc etc from source to target and we’re done! I was so close.
Alas: when I try to modify the subMeshCount of target in any way, unity produces the following error:
No line number, no error code. There is only srcIB. srcIB into eternity.
For this reason, I’ve used a for loop and iterated through setTriangles and getTriangles in order to correctly set the submeshes. The submeshes are critical.
Under this situation, I can get the script to behave as expected only under certain circumstances. Observe:
1. Open unity and look at object. It produces a submesh out of bounds error and some elements of the mesh are missing.
2. Get the script, remove the setTriangles for loop and replace it with subMeshCount = 7 (arbitrary number). Unity makes the srcIB error.
3. Remove the subMeshCount assingment and put the for loop back. The script is now identical to step one. The mesh will now work correctly.
I have a feeling that the array shit is probably not the priority anymore in this problem, but for what it’s worth: Since i don’t want to instantiate thousands of meshes in Update, I’m doing new Mesh() in the class declaration and so i can’t support a potentially infinite number of them like a reasonable script would. That’s why the array is written the way that it is.
I have a suspicion that I should make a new question for this.
Anyway, my brain is melting out of my ears trying to comprehend some of this behaviour. Any pointers or helpers would be really appreciated - thank you so so much. Have fun trying to crack this one :slight_smile:_