Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by dreadofmondays · Dec 22, 2015 at 09:05 AM · c#mesheditor-scriptingarraysmesh-deformation

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: http://puu.sh/m4qgV/46df26f5f0.png 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. Thanks.

Comment
Add comment · Show 4
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image wibble82 · Dec 22, 2015 at 11:04 AM 0
Share

Hi

We need to see your code and the full error (with line number) to answer this.

I am guessing when you say 'gives an error', you mean 'raises an exception when you run it', rather than 'gives a compile error'? I would be surprised if the exception is occurring on the line you show - perhaps it is, but I'd like to see that for certain before going into more detail!

-Chris

avatar image wibble82 · Dec 22, 2015 at 11:07 AM 0
Share

Just noticed the code is the screen shot. Will take a look. Please use the code button in future to post code (the little 101010 icon in the text editor).

avatar image wibble82 · Dec 22, 2015 at 11:14 AM 0
Share

Ok, ideally I'd have the code to explain this, but as a first step, could you:

Go back to your original code, and make 100% certain it still works with absolutely no other changes whatsoever to your scene (I want to make totally certain this isn't related to the mesh you're using).

Next, we'll make the $$anonymous$$imal change possible to achieve your goal. All we're going to do is on the first line of your original code, change it to:

                 $$anonymous$$esh[] newGraphic$$anonymous$$eshes = { new $$anonymous$$esh(), new $$anonymous$$esh() };
                 $$anonymous$$esh target = newGraphic$$anonymous$$eshes[0];

If it is indeed purely related to storing the meshes in an array, then this should give the same issue, as we're still creating the array, and still writing to the first mesh in the array.

-Chris

avatar image wibble82 · Dec 22, 2015 at 11:16 AM 0
Share

Also - please still paste in your full code (with my modifications) so I can see what else is going on around it!

3 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by Bunny83 · Dec 22, 2015 at 01:50 PM

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[i] = new Mesh(); // but create your meshes here.
     // ...
 }

ps:
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.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image dreadofmondays · Dec 22, 2015 at 01:53 PM 0
Share

When does start run in the editor?

avatar image Bunny83 dreadofmondays · Dec 22, 2015 at 01:57 PM 0
Share

Just like it would at runtime, the moment your scripts has been recompiled before the first Update call.

avatar image dreadofmondays Bunny83 · Dec 22, 2015 at 02:27 PM 0
Share

I will try it soon, i need a break for today.

avatar image
-1

Answer by dreadofmondays · Dec 22, 2015 at 01:22 PM

@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;
 
 [ExecuteInEditMode]
 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) {
             Destroy(this);
         }
     }
 
     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); 
             j++;
         }
         mf.sharedMesh = target;
         mf.sharedMesh.vertices = vertices;
         mf.sharedMesh.RecalculateBounds();
         mf.sharedMesh.RecalculateNormals();
 
         //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++) {
             TransformGraphicMesh(0);
             Debug.Log("k is "+k);
         }*/
     }
 
     void OnDrawGizmos()
     {
         for (int i = 0; i < connectors.Length; ++i) {
             Gizmos.DrawWireSphere(connectors[i].position, 1.0f);
             Gizmos.DrawRay(connectors[i].position, connectors[i].forward*2);
         }
     }
 
     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:

 srcIB

http://puu.sh/m4iii/cfe1331d27.png 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 :)

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image aaronjbaptiste · Jan 23, 2016 at 10:38 AM 0
Share

Did you solve the srcIB error? I'm getting it on my project when setting sub$$anonymous$$eshCount. Any ideas?

avatar image dreadofmondays aaronjbaptiste · Jan 23, 2016 at 01:02 PM 0
Share

I was never able to solve the underlying cause of the srcIB error, and i had to take a different approach; ins$$anonymous$$d of making an empty mesh and assigning properties, I figured out how to instantiate a new copy of the mesh and then modified that, keeping the sub$$anonymous$$eshCount intact and making it unnecessary to directly modify it. Sorry dude

avatar image
0

Answer by dreadofmondays · Dec 24, 2015 at 02:55 AM

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!

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

7 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Moving an hole in a plane 0 Answers

how do i fix how i make triangels in my mesh 0 Answers

Mesh deformation with collisions 2 Answers

How to resave generated meshes with Editor Scripts? 0 Answers

Setting mesh.vertices to a 3-dimensional array 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges