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