- Home /
Can I store a mesh in a class variable ?
No soup for you, and no answer for me =[
Of course Unity has been screaming at me : You are trying to create a MonoBehaviour using the 'new' keyword. This is not allowed. But following the Burgzerg Arcade series, he says this is ok ignore the warning. Guess I need to find out the correct way to create, declare, then assign a variable that is a class variable. I feel Bunny83 has most closely identified the problem, however I am still bamboozled.
Revised Description :
So I make a class with some variables :
#pragma strict
public class CubeFace extends MonoBehaviour
{
public var faceMesh : Mesh;
public var faceMeshFilter : MeshFilter;
public var cubeVerts : Vector3[];
public var sphereVerts : Vector3[];
public var uvs : Vector2[];
public var norms : Vector3[];
public var tris : int[];
}
public class CubeToSphereMap extends MonoBehaviour
{
// this is the main body of the script
}
Within the main body of the script, I declare and assign :
private var meshUp : CubeFace;
private var meshDown : CubeFace;
// 4 more
Then through some functions, all those variables get populated :
theFace = new CubeFace();
theFace.cubeVerts = SomeCalculatedVerts;
theFace.sphereVerts = SomeMoreCalculatedVerts;
theFace.uvs = SOmeUvCoordinates;
theFace.tris = commonTris;
theFace.norms = commonNorms;
After all that happens, I build my mesh with the information :
if ( useCube )
{
theMesh.vertices = theFace.cubeVerts;
}
else
{
theMesh.vertices = theFace.sphereVerts;
}
theMesh.uv = theFace.uvs;
theMesh.triangles = theFace.tris;
theMesh.normals = theFace.norms;
theMesh.RecalculateBounds();
theMesh.RecalculateNormals();
Ok, now directly after that , the very next line, I have tried :
//theFace.faceMesh = new Mesh();
theFace.faceMesh = theMesh;
theFace.faceMeshFilter = go.GetComponent( MeshFilter );
Now in anything before where I have needed to call upon the mesh reference again, I simply use theMesh.vertices = modifiedVerts; Now when I try to do exactly the same thing, except this time the myMesh variable isn't on this script, it's a variable of another class variable :
//meshUp.faceMeshFilter.mesh.vertices = meshUp.sphereVerts;
Debug.Log( "cacheMesh " + meshUp.faceMesh );
Debug.Log( "filter " + meshUp.faceMeshFilter );
And it throws a null. And I throw something too ....
Original Question
I have a class that stores the same type of information for 6 gameObjects. It creates those gameObjects and their meshes. So this is on an empty gameObject, and the 6 mesh objects have no script :
public class CubeFace extends MonoBehaviour
{
public var faceMesh : Mesh;
public var faceMeshFilter : MeshFilter;
// etc
}
public class CubeToSphereMap extends MonoBehaviour
{
private var meshUp : CubeFace;
// etc
}
I have no problem generating the meshes, and both sets of vertices are yielding the expected results :
function ConstructFace( theFace : CubeFace, theName : String, theRotation : Vector3, theMaterial : Material )
The problem came while trying to modify the vertices variable of the mesh reference that was stored in the variable of the class.
theMesh.vertices = theFace.cubeVerts; // sphereVerts; // both work happily, I have my mesh
// etc etc etc
theMesh.RecalculateNormals();
// NOW HERE I am trying to store a reference to my mesh
// to modify the vertices later
theFace.faceMesh = theMesh;
theFace.faceMeshFilter = go.GetComponent( MeshFilter );
So the mesh is made, but when I try to modify the verts, I get the null reference to the Mesh, and after trying another approach the MeshFilter.
meshUp.faceMesh.vertices = meshUp.sphereVerts;
meshUp.faceMeshFilter.mesh.vertices = meshUp.sphereVerts;
Debug.Log( "cacheMesh " + meshUp.faceMesh );
Debug.Log( "filter " + meshUp.faceMeshFilter );
Huh ?!
6 variables of the class CubeFace are made.
information is happily stored to those class variables
meshes are happily made reading the information of the CubeFace class
but when I try to access either faceMesh or faceMeshFilter, I get a null reference exception : NullReferenceException: Object reference not set to an instance of an object CubeToSphereMap.ShowAsSphere () (at Assets/_Scripts/CubeToSphereMap.js:100)
Debug.Log( "cacheMesh " + meshUp.faceMesh ); Debug.Log( "filter " + meshUp.faceMeshFilter );
I hope it is not something obvious, run out of ideas and need suggestions. Many Thanks =]
The image is to show I have no problem at all making my meshes, the problem is storing that Mesh/MeshFilter in a variable.
It might be silly, but have you tried making your variables private and then setting and getting them using functions?
Answer by whydoidoit · Mar 22, 2013 at 01:13 PM
Ok I know what your problem is:
You are never assigning meshUp/meshDown etc - here's why:
You pass the value for meshUp to ConstructFace (it\'s probably null), in ConstructFace you create a new CubeFace but assigning that to the variable of the parameter does not change the private variable in your class. That's not how it works (it kinda does in C# with the ref keyword) but not here.
I suggest you return the CubeFace from ConstructFace:
function ConstructFace(theName : String, theRotation : Vector3, theMaterial : Material ) : CubeFace
{
...
return theFace;
}
Then:
meshUp = ConstructFace("CubeFace_Up", Vector3.right * 270, mtlUp );
$$anonymous$$ike, you are a legend, this is a fact.
This must be the part I don't understand between modifying a variable and returning an instance/copy of that variable.
I get completely lost when you guys talk instances, inheritance, serialization, etc etc
nnneeeeooOOOOoooowww that was airplane flight number Understanding-One flying right over my head.
Couldn't understand why there was no further help for me on this. Was it a stupid question? Was it expected of me to be able to work it out myself? As you saw when you answered my silly question where I didn't increment my loop variable, sometimes things just are not as obvious to me as they should be.
Thank you so much for this. I have now learned : when passing a class variable to a function, return the variable so it indeed becomes populated. You have helped me greatly. Digital bottle of vino on me. All the Best.
Thanks to Bunny83 too, always been there with good technical advice (and support of my answers), and robertblu for effort and constructive help (and all his efforts this year).
Yeah you can modify an existing class too - so either you should have created it before calling the ConstructFace function and used it, or created it in there and returned it :)
As I was fixing it I also immediately noticed the line theFace = new CubeFace(); was in the construct function, and it dawned on me that the variable was declared but not really in 'existence' (assigned, is that right?). Thanks again, you have shown me a lot.
You declared it outside, but never assigned anything to it, so it was most likely null (the public one was probably created by Unity, it does that sometimes). As for the instance you filled out: you created it in ConstructFace and promptly ignored it as soon as the function exited - so actually it became unreachable and was never assigned.
You can't return values by assigning to a parameter in Unity Script (you can in C# using ref in front of the parameter).
Answer by selzero · Mar 04, 2013 at 05:20 PM
Have you tried recalculating bounds?
http://www.gamasutra.com/blogs/DenizOpal/20120922/178132/Manipulating_Meshes_in_Unity3D.php
Yes, the$$anonymous$$esh.RecalculateBounds(); is called after the values from the class have been assigned. Now why does neither the mesh filter nor the mesh want to store themselves in the same class as where the information to create them came from? Why is it on a single script, if the$$anonymous$$esh is a global variable, that I can happily call it all day long, but when I assign it to a variable in a class variable, it suddenly becomes null ?
Answer by robertbu · Mar 04, 2013 at 05:52 PM
My knowledge of meshes is shallow, but I have a couple of theories in my head. As a debugging step, anywhere you assign the mesh you created to a MeshFilter, replace it by assigning a Mesh.Instantiate()'ed copy of the mesh and see what happens.
Answer by Bunny83 · Mar 04, 2013 at 07:23 PM
First of all this line:
public class CubeFace extends MonoBehaviour
and this line:
theFace = new CubeFace();
don't work together. Your CubeFace class is derived from MonoBehaviour, but you can't created an instance with "new". MonoBehaviour classes have to be attached to a gameobject and can only be created with AddComponent.
Also you always talk about "main body" and "some functions" but when exactly is your mesh created? In other words when are your "some functions" called?
What is "go" and are you sure that this gameobject has a MeshFilter / MeshRenderer?
Also is that all happening at runtime? Or do you try to save the meshes as assets in the editor?
Thanks for the reply. Here is the full script : http://www.alucardj.net16.net/unityquestions/CubeToSphere$$anonymous$$ap.js
I didn't post it as you have answered the cube to spheremap qn and prevent this being copied and reappearing later.
Of course Unity has been screa$$anonymous$$g at me : You are trying to create a $$anonymous$$onoBehaviour using the 'new' keyword. This is not allowed. But following the Burgzerg Arcade series, he says this is ok ignore the warning. Guess I need to find out the correct way to create, declare, then assign a variable that is a class variable.
The times I have successfully used class, it was within a class, eg :
#pragma strict
public class NameOfClass extends $$anonymous$$onoBehaviour
{
public var someInt : int = 0;
private var someFloat : float = 0.0;
class waypointInfo
{
var wayPosition : Vector3;
var wayParent : Vector3;
var scoreF : float = 0.0;
var scoreG : float = 0.0;
var scoreH : float = 0.0;
}
function DoStuff()
{
}
}
and this has worked fine. I shall try my CubeToSphere$$anonymous$$ap script without the class extending monobehaviour (as you suggest), therein may be the new problem. Thankyou for the input, hope the full script clears up any questions. This is just a test project, am learning on the fly, so yes things could be done differently / better.
Edit :
just tested public class CubeFace // extends $$anonymous$$onoBehaviour , it has the same problem. I am going to test just storing a reference to the gameObject first to see if im making some obvious mistake.
.... wow so I am really lost. I just made meshUp public, ran the thing and checked the inspector. There are no values, not even for the verts. So where the heck are my vert values co$$anonymous$$g from and being stored to? Completely lost, walking away for now ....
Edit 2 :
And after a quick test the same result here : http://www.alucardj.net16.net/unityquestions/CubeToSphere$$anonymous$$apOneClass.js
I am totally baffled, if var meshUp : CubeFace; is being used to store my vertices which are then read to generate the mesh, where and why are the values in the inspector empty?