- Home /
function that returns multiple variables (in this case, lists)
Hi there, is it possible to make a function that returns multiple variables? More specifically for my example, multiple lists. My application is procedural mesh generation, in which I am calling my own mesh generators and mesh effects that I have coded in static scripts. Previously, I have been setting up a gameObject in one script, and calling a mesh generator in another, to which I pass a mesh. Then I pass the new mesh to several mesh effects one at a time which each return the new mesh before being passed to the next. I feel there should be a quicker way than this (while still keeping my code modular), so I am now trying to pass each generator and effect function a series of lists (for verts, tris, uvs and normals) instead of the mesh. When I pass the mesh to a function, it is passed as a reference and therefor doesn't need return to continue work on it. When I pass the lists however, they are not referenced, and I therefor need a way to return the 4 lists. Here is an attempt of mine at returning the lists:
The function that sets up the gameObject:
void TerrainGenerator (int xQ, int yQ, float w, float d) {
List<Vector3> verts = new List<Vector3> ();
List<int> tris = new List<int> ();
List<Vector2> uv = new List<Vector2> ();
List<Vector3> norms = new List<Vector3> ();
GameObject quad = new GameObject ("Quad", typeof(MeshFilter), typeof(MeshRenderer));
Mesh mesh = new Mesh ();
MeshGenerators.CreatePlane (verts, tris, uv, norms, xQ, yQ, w, d);
mesh.vertices = verts.ToArray();
mesh.triangles = tris.ToArray();
mesh.uv = uv.ToArray();
mesh.normals = norms.ToArray();
MeshFilter mesh_filter = quad.GetComponent<MeshFilter> ();
mesh_filter.mesh = mesh;
MeshRenderer mesh_renderer = quad.GetComponent<MeshRenderer> ();
mesh_renderer.material = quadMaterial;
}
and the generator function that is called by the above function:
public static void CreatePlane (List<Vector3> vertices, List<int> triangles, List<Vector2> uv, List<Vector3> normals, int xQuads, int yQuads, float quadWidth, float quadDepth) {
for (int y = 0; y <= yQuads; y++) {
for (int x = 0; x <= xQuads; x++) {
vertices.Add (new Vector3 (x * quadWidth, y * quadDepth, 0));
normals.Add (Vector3.up);
uv.Add (new Vector2 ( x / (xQuads), y / (yQuads) ));
}
}
for (int y = 0; y < yQuads; y++) {
for (int x = 0; x < xQuads; x++) {
triangles.Add ( 0 + x + (xQuads + 1) * y );
triangles.Add ( 1 + x + (xQuads + 1) * y );
triangles.Add ( 1 + x + (xQuads + 1) * (y + 1) );
triangles.Add ( 0 + x + (xQuads + 1) * (y + 1) );
}
}
return vertices;
return triangles;
return uv;
return normals;
}
I'm not sure it's even possible, but any pointers would be greatly appreciated. Also, if you don't think there would be any advantage to passing the lists over passing the mesh itself, do tell!
Cheers in advance,
Pete
Answer by Dave-Carlile · Jul 13, 2015 at 04:57 PM
When passing a List (or any class) as a parameter to a function, it is always passing a reference to the list. So anything you do to the list contents (e.g. adding a vertex) is being done to the original because they're pointing to the same thing. The only time you would need to pass back the list reference itself is if you're creating a new list instance, and it doesn't look like you're doing that.
That said, if you need to deal in the list references themselves, pass them as ref parameters.
void DoSomething(ref List<Vector3> vectors)
{
vectors = new Vectors(); <-- the caller will get a new instance
}
List<Vector3> v = null;
DoSomething(ref v); <-- v will come back with a new list instance
But again, I don't think you need to do that in your case. You're creating the lists before you call the functions and the functions are just altering the contents.
And unless you're ever going to be creating non-Unity meshes, you may as well just pass the Mesh instance around instead of the individual properties.
I thought I'd tested to see if altering the list without any kind of return code would affect it, maybe I missed something though, I'll report back on that.
But you reckon I'd be just as well off passing the mesh ins$$anonymous$$d? Well, that is much easier to code! I'll still test the lists in order to wrap this question up (might come in handy for something else). I might even do a little performance test to see if there is a notable difference.
Cheers for your help Dave!
Pete
Ok you're right, it does work without any kind of out/ref/return. I think I'd bodged up the triangles on that particular attempt (I'd added 4 per quad ins$$anonymous$$d of 6... doh!) and mistook it for the lists not working.
If I get a chance to do a performance test, I'll report back again.
Cheers again!
Pete