Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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 AlucardJay · Oct 18, 2012 at 11:39 PM · mesharraylength

array out of range while updating mesh variables

Original Question :

I have a string that is converted to a custom text mesh.

Whenever the size of the Built-In arrays are changed, for the first frame/loop/cycle I get out of range errors :

Mesh.vertices is too small. The supplied vertex array has less vertices than are referenced by the triangles array. UnityEngine.Mesh:set_vertices(Vector3[]) SText:UpdateTextChar() (at Assets/_Custom/Sprites/SText.js:145) SText:UpdateText(String) (at Assets/_Custom/Sprites/SText.js:172) UI_Manager:UpdateStats() (at Assets/_Scripts/UI_Manager.js:202) UI_Manager:Update() (at Assets/_Scripts/UI_Manager.js:102)

Mesh.uv is out of bounds. The supplied array needs to be the same size as the Mesh.vertices array. UnityEngine.Mesh:set_uv(Vector2[]) SText:UpdateTextChar() (at Assets/_Custom/Sprites/SText.js:146) SText:UpdateText(String) (at Assets/_Custom/Sprites/SText.js:172) UI_Manager:UpdateStats() (at Assets/_Scripts/UI_Manager.js:202) UI_Manager:Update() (at Assets/_Scripts/UI_Manager.js:102)

Mesh.normals is out of bounds. The supplied array needs to be the same size as the Mesh.vertices array. UnityEngine.Mesh:set_normals(Vector3[]) SText:UpdateTextChar() (at Assets/_Custom/Sprites/SText.js:148) SText:UpdateText(String) (at Assets/_Custom/Sprites/SText.js:172) UI_Manager:UpdateStats() (at Assets/_Scripts/UI_Manager.js:202) UI_Manager:Update() (at Assets/_Scripts/UI_Manager.js:102)

I cannot understand it, as this worked without error when running Unity 3.5.1, but now running 3.5.6 I have this error across all projects where I have used my sprite and text classes.

The arrays are set by the length of the string before the mesh is generated in UpdateTextMesh(). I have tried merging this function with UpdateTextChar() and using helloStringLength instead of .length in every subsequent for-loop, but it makes no diference. I cannot see how the arrays are being assigned the wrong length for the first cycle when helloStringLength changes size.

Here is my SText Script :

 #pragma strict
 @script RequireComponent(MeshFilter, MeshRenderer)
 
 #if UNITY_EDITOR
 @ContextMenu ("Construct sText")
 function ConstructText() 
 {
     Debug.Log("Constructing sText from ContextMenu");
     ConstructOnCreation();
 }
     
 function ConstructOnCreation() 
 {
     if(!myTextMesh)
     {
         GetComponent(MeshFilter).mesh = myTextMesh = new Mesh();
         myTextMesh.name = "sTextMesh";
     }
     
     UpdateText( helloString );
 }
 #endif
 
 public class SText extends MonoBehaviour
 {
     public var textSheetInfo : TextAsset;
     public var textureWidth : int;
     public var textureHeight : int;
         
     public var helloString : String = "Hello";
     
     public var charSize : float = 1.0;
     public var _char_id : int[]; 
     public var _char_x : int[]; 
     public var _char_y : int[]; 
     public var _char_width : int[]; 
     public var _char_height : int[]; 
     public var _char_xoffset : int[]; 
     public var _char_yoffset : int[]; 
     public var _char_xadvance : int[]; 
         
     private var myTextMesh : Mesh;
     private var uv : Vector2[];
     private var verts : Vector3[];
     private var tris : int[];
     private var normals : Vector3[];
     private var size : Vector2 = Vector2.one;
     private var offset : Vector2 = Vector2(0.0, 0.0);
     private var uvSize : Vector2 = Vector2(1.0, 1.0);
     private var uvOffset : Vector2 = Vector2(0.0, 0.0);
     
     private var letter : String;
     private var textAlignX : float = 0.0;
     private var textAlignY : float = 0.0;
     public var textPaddingX : float = 0.0;
     
     
     function Awake() 
     {
         if(!myTextMesh)
         {
             GetComponent(MeshFilter).mesh = myTextMesh = new Mesh();
             myTextMesh.name = "sTextMesh";
         }
         
         UpdateText( helloString );
     }
     
     function Start() 
     { 
         yield WaitForSeconds( 2.0 );
         
         UpdateText( "Droogie" );
         
         yield WaitForSeconds( 2.0 );
         
         UpdateText( "Droogie !..!, ('.') ,!..!" );
     }
     
     function Update() { 
     }
     
     
     // CONSTRUCTING Text
     
     function UpdateTextMesh() 
     {
         var helloStringLength : int = helloString.Length;
         
         verts = new Vector3[helloStringLength * 4];
         uv = new Vector2[helloStringLength * 4];
         tris = new int[helloStringLength * 6];
         normals = new Vector3[helloStringLength * 4];
         
         myTextMesh = this.transform.GetComponent(MeshFilter).mesh as Mesh;
         
         
         var readString : int = 0;
         textAlignX = 0;
         textAlignY = 0;
         
         for (readString = 0; readString < helloStringLength; readString ++)
         {
             letter = helloString.Substring( readString, 1 );
             
             var uniString : int = (letter[0]);
                                 
             uvSize = Vector2( parseFloat(_char_width[uniString]) / parseFloat(textureWidth), 
                              parseFloat(_char_height[uniString]) / parseFloat(textureHeight) );
             
             uvOffset = Vector2( parseFloat(_char_x[uniString]) / parseFloat(textureWidth), 
                                 parseFloat(_char_y[uniString]) / parseFloat(textureHeight) );
             
             size = Vector2( parseFloat(_char_width[uniString]), parseFloat(_char_height[uniString]) );
             
             offset = Vector2( parseFloat(_char_xoffset[uniString]), parseFloat(_char_yoffset[uniString]) );
             
             textAlignX += _char_xoffset[uniString];
             textAlignY = 0 -  ( _char_yoffset[uniString] * 0.5 );
             
             // BuildTextChar
             verts[(readString * 4) + 0] = new Vector3( ( textAlignX + offset.x ) * (charSize / 64), ( 0 - offset.y ) * (charSize / 64), 0);
             verts[(readString * 4) + 1] = new Vector3( ( textAlignX + offset.x + size.x ) * (charSize / 64), ( 0 - offset.y ) * (charSize / 64), 0);
             verts[(readString * 4) + 2] = new Vector3( ( textAlignX + offset.x ) * (charSize / 64), ( 0 - offset.y - size.y ) * (charSize / 64), 0);
             verts[(readString * 4) + 3] = new Vector3( ( textAlignX + offset.x + size.x ) * (charSize / 64), ( 0 - offset.y - size.y ) * (charSize / 64), 0);
             
             uv[(readString * 4) + 2] = new Vector2(uvOffset.x, 1.0 - uvOffset.y - uvSize.y);
             uv[(readString * 4) + 3] = new Vector2(uvOffset.x + uvSize.x, 1.0 - uvOffset.y - uvSize.y);
             uv[(readString * 4) + 0] = new Vector2(uvOffset.x, 1.0 - uvOffset.y);
             uv[(readString * 4) + 1] = new Vector2(uvOffset.x + uvSize.x, 1.0 - uvOffset.y);
             
             tris[(readString * 6) + 0] = (readString * 4) + 0;
             tris[(readString * 6) + 1] = (readString * 4) + 1;
             tris[(readString * 6) + 2] = (readString * 4) + 2;
             tris[(readString * 6) + 3] = (readString * 4) + 2;
             tris[(readString * 6) + 4] = (readString * 4) + 1;
             tris[(readString * 6) + 5] = (readString * 4) + 3;
         
             textAlignX += textPaddingX + _char_xadvance[uniString];
         }
         
         
         myTextMesh.vertices = verts;
         myTextMesh.uv = uv;
         myTextMesh.triangles = tris;
         myTextMesh.normals = normals;
         
         myTextMesh.RecalculateBounds();    
         myTextMesh.RecalculateNormals();
         
         // Calculate Tangents
         TangentSolver(myTextMesh);
         
     }
     
     
     // UPDATING Text
     
     public function UpdateText( textString : String )  // TEXT
     {
         helloString = textString;
         //transform.position = Vector3(posX, posY, layer); // transform.position.z
         //textPaddingX = padding; // 0.0;
         
         UpdateTextMesh();
     }
     
 }

Here is the script I am using to update the speed :

 public var speedText : SText;
 
 function Update() 
 {
     speedText.UpdateText( parseInt( currentSpeed ).ToString() );
 }


EDIT :

From the advice I have received from Kryptos and phodges, the title of the question should now be :

How do I correctly create and optimize my meshes, and correctly modify the vertex information per change in vertices alone, and/or triangles & uvs length or values ?

Since I learned mesh generation, my procedure was as follows :

  • declare builtin arrays to store and calculate the vertex information

  • declare the size of these arrays

  • calculate verts / uvs / tris / normals

  • get the mesh filter / mesh

  • assign the mesh vertex arrays the same length as the builtin arrays' lengths

  • assign all the values from the builtin arrays to the mesh vertices etc

  • RecalculateBounds and RecalculateNormals

when I am animating vertices per update :

  • use the builtin arrays and make calculations

  • simply assign mesh.vertices = builtin array verts;

this can be seen in the scripts of all my progressive mesh related questions :

http://answers.unity3d.com/questions/277222/simply-assign-tangents-to-single-quad.html

http://answers.unity3d.com/questions/305515/irregularities-with-procedurally-generated-sphere.html

http://answers.unity3d.com/questions/314373/most-efficient-way-to-declare-and-assign-variables.html

So am now wondering : is the correct methd of creating and optimizing mesh generation and manipulation is to :

  • find the mesh filter mesh

  • directly assign the lengths to the different vertex arrays

  • directly assign values to the different vertex arrays

  • RecalculateBounds and RecalculateNormals

when I am animating vertices per update :

  • find the mesh filter mesh

  • clear the mesh

  • directly assign the lengths to the different vertex arrays

  • directly assign values to the different vertex arrays

  • RecalculateBounds and RecalculateNormals

If I am doing something wrong please let me know, I am self taught, only used Unity this year, coming from a very limited ability using basic and actionscript2 (mostly just logic-gate calcs and printout stuff) and admit I need to know more about many things (I don't have a clue about shaders, stack and flow, many other optimization or efficiency techniques, or just the right way to use Unity). If you can guide me I am very grateful.


Comment
Add comment · Show 3
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 Kryptos · Oct 19, 2012 at 03:16 PM 0
Share

Not related to your issue but these lines are useless:

 myText$$anonymous$$esh.vertices = new Vector3[verts.length];
 myText$$anonymous$$esh.uv = new Vector2[uv.length];
 myText$$anonymous$$esh.triangles = new int[tris.length];
 myText$$anonymous$$esh.normals = new Vector3[normals.length];

Since you reaffect arrays in the following lines.

avatar image AlucardJay · Oct 21, 2012 at 07:25 AM 0
Share

Thanks for that information. It was an attempt to again assign the length of the arrays correctly to clear the error of the incorrect vert to tri lengths. I have edited my question asking for more information.

avatar image AlucardJay · Oct 29, 2012 at 11:15 AM 0
Share

The solution was mesh.Clear();

4 Replies

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

Answer by Kryptos · Oct 19, 2012 at 03:19 PM

Don't reuse a mesh, always create a new one (it is safer):

 // don't do
 myTextMesh = this.transform.GetComponent<MeshFilter>().mesh;    
 // do that instead
 myTextMesh = new Mesh();
 
 // and after creation
 this.GetComponent<MeshFilter>().mesh = myTextMesh;

Or if you don't like recreating then don't forget to clear the mesh (especially when the number of triangles changes):

 myTextMesh.Clear();

edit: Sorry I mixed up C# and US. Now all my code example are in C#.

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 AlucardJay · Oct 21, 2012 at 08:19 AM 0
Share

This is what I tried :

  //GetComponent($$anonymous$$eshFilter).mesh = myText$$anonymous$$esh = new $$anonymous$$esh();
  myText$$anonymous$$esh = new $$anonymous$$esh();
  this.GetComponent().mesh = myText$$anonymous$$esh;
  myText$$anonymous$$esh.name = "sText$$anonymous$$esh";

and these are my errors :

Assets/_Custom/Sprites/SText.js(16,39): BCE0043: Unexpected token: ).

Assets/_Custom/Sprites/SText.js(16,40): BCE0044: expecting ), found '.'.

Assets/_Custom/Sprites/SText.js(16,41): UCE0001: ';' expected. Insert a semicolon at the end.

these are all on the line

 this.GetComponent<$$anonymous$$eshFilter>().mesh = myText$$anonymous$$esh;

do I have the format of this correct for uJS ?

 GetComponent<$$anonymous$$eshFilter>()

Thanks.

avatar image phodges · Oct 21, 2012 at 08:29 AM 0
Share

GetComponent($$anonymous$$eshFilter) in uJS.

avatar image AlucardJay · Oct 21, 2012 at 08:40 AM 0
Share

Thanks, I should have realized this is just an expanded variation on what I already use on creation :

  //GetComponent($$anonymous$$eshFilter).mesh = myText$$anonymous$$esh = new $$anonymous$$esh();
  myText$$anonymous$$esh = new $$anonymous$$esh();
  this.GetComponent($$anonymous$$eshFilter).mesh = myText$$anonymous$$esh;
avatar image
0

Answer by andisopany · Oct 19, 2012 at 02:47 AM

Are you taking the default mesh and adding values to it before setting its size?

I didn't look too close but it looks like you are getting your mesh from the gameobject and then stuffing values into it. How do you know its the right size?

Comment
Add comment · Show 4 · 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 andisopany · Oct 19, 2012 at 02:52 AM 0
Share

hmm, it says you are supposed to call Clear() on the mesh before assigning the vertices.

avatar image andisopany · Oct 19, 2012 at 02:53 AM 0
Share

http://docs.unity3d.com/Documentation/ScriptReference/$$anonymous$$esh.html

avatar image AlucardJay · Oct 19, 2012 at 05:31 AM 0
Share

I am building my own mesh, and the arrays are populated by another script (a parser that reads the bmfont text file and stuffs the information in). The text displays and changes to the text all work as expected, even with the error.

now, imagine helloString is "10", when the length of helloString changes eg "100" so length has gone from 2 to 3. then on the first execution of the function UpdateText() I get the errors, but the next frame/loop/cycle the mesh updates, it populates the arrays with no error, it displays and works fine.

The arrays are set at the start of the function, before any vertices are calculated. And I cannot see a way that helloSting.length is changing between assigning the length of the arrays and the assigning the values in those arrays.

Again, this only happens once when the length of helloString changes.

Thanks for your comments though =]

avatar image AlucardJay · Oct 19, 2012 at 05:33 AM 0
Share

As this isn't a solution, could you please convert this to comment? Thanks =]

avatar image
0

Answer by phodges · Oct 19, 2012 at 05:44 AM

In your code, you are setting the arrays twice; once to some unused arrays of the same size as your data and then directly afterwards. That seems a little redundant so I would get rid of the first stage and also do as anisopany suggests and call clear on the mesh before the assignment.

Comment
Add comment · Show 4 · 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 AlucardJay · Oct 19, 2012 at 05:56 AM 0
Share

With every script that I create a mesh (be it a quad, icosahedron, sphere, 'sock', etc), I do all my calculations and store them in local cache'd builtin arrays, then when the calculations are complete I assign the information in these arrays to the variables of the mesh. I have examples of procedurally generated meshes that have the vertices animated per frame all without ever using Clear(). This is mostly due to the fact that most of my meshes don't change in length. As this one does, I shall indeed try Clear(); but to reiterate the problem, the errors only occur once when the length of helloString changes. The script works fine in every other aspect. Thanks.

avatar image phodges · Oct 19, 2012 at 06:01 AM 1
Share

The more I look at it, the less I like the redundant assignments (and array allocation). Do try removing those lines.

avatar image Kryptos · Oct 19, 2012 at 03:20 PM 0
Share

I agree with @phodges. There are useless and even expensive because the internal $$anonymous$$esh is recreated twice.

avatar image AlucardJay · Oct 21, 2012 at 07:32 AM 0
Share

I admit I need to learn and understand more. Am rewriting the SText class now considering this (phodges) and $$anonymous$$ryptos answer.

avatar image
0

Answer by phodges · Oct 21, 2012 at 09:44 AM

In answer to your latest version, the reason that you see nothing is because you are assigning the arrays too early. Take a look at the following snippet as an example, it's written in C# but only the comments are really important:

 using UnityEngine;
 using System.Collections;
 
 [RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
 public class MeshDemo : MonoBehaviour {
 
      void Awake() {
                CreateMesh();
      }
 
      void CreateMesh() {
         MeshFilter filter = GetComponent<MeshFilter>();
         Mesh mesh = new Mesh();
         
         // Simple demo mesh
         Vector3[] vx = new Vector3[4];
         Vector2[] uv = new Vector2[4];
         Vector3[] n = new Vector3[4];
         int[] ix = new int[6];
 
         // If you want to never see the mesh then assign properties here and comment out the lower assignments.
         /*
         mesh.vertices = vx;
         mesh.uv = uv;
         mesh.normals = n;
         mesh.triangles = ix;
         */
 
         for (int i=0; i<4; ++i){
             vx[i].x = 0 != (i&1) ? -1f : 1f;
             vx[i].z = 0 != (i&2) ? -1f : 1f;
             n[i] = Vector3.up;
             uv[i].x = 0 != (i&1) ? 0f : 1f;
             uv[i].y = 0 != (i&2) ? 0f : 1f;   
         }
         ix[0] = 0; ix[1] = 2; ix[2] = 1;
         ix[3] = 1; ix[4] = 2; ix[5] = 3;

         // Now that all the values are defined we can assign them to the mesh,
         mesh.vertices = vx;
         mesh.uv = uv;
         mesh.normals = n;
         mesh.triangles = ix;
 
         Debug.Log("Mesh ready");
         filter.mesh = mesh;
     }
 }
 
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 AlucardJay · Oct 24, 2012 at 12:39 AM 0
Share

I'm sorry but I really don't understand. In your example you create temporary arrays, use them in your calculations, then assign them to the mesh. This is exactly what I am doing. So I really fail to see how I am duplicating or using redundant assignments. This whole thing is getting further from my actual problem (and actual question), and I have just simply been left here confused.

avatar image phodges · Oct 24, 2012 at 05:36 AM 0
Share

I've seen people become confused by this point before. In the code sample above, we have temporary references to arrays (vx,ux, etc.) the arrays themselves are not temporary (or at least they are of the same scope as mesh).

In the block that was commented out, we trigger the internal processes of $$anonymous$$esh too early by making the various property assignments; each array entry will still have its default values at this point. In particular, since the index array will be full of zeroes, the mesh builder will construct a mesh based on a single point (or possibly even optimise it out).

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

12 People are following this question.

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

Related Questions

Best Way to Link Vertices into Mesh 0 Answers

c# array size doesn't grow past 10 (bracket initialization) 2 Answers

How to load all vertices form multiple children of a game object in to one big array? 0 Answers

Getting length of array based on a loop search? 1 Answer

Generate a mesh from randomly positioned points 0 Answers


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