[SOLVED] MeshInstance not showing in scene

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By DaddyMonster

I’m new to gdscript and I’m going through the docs and thought creating a simple mesh using ArrayMesh would be a solid starting point.

I have one scene (MainScene) with a spatial node, a camera and a directional light. My other scene (Triangle) is MeshInstance and I’ve added the following script to it (lifted from the docs):

extends MeshInstance

func _ready():
	var vertices = PoolVector3Array()
	
	vertices.push_back(Vector3(0, 1, 0))
	vertices.push_back(Vector3(1, 0, 0))
	vertices.push_back(Vector3(0, 0, 1))
	
	# Initialize the ArrayMesh.
	var arr_mesh = ArrayMesh.new()
	var arrays = []
	arrays.resize(ArrayMesh.ARRAY_MAX)
	arrays[ArrayMesh.ARRAY_VERTEX] = vertices
	
	# Create the Mesh.
	arr_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, arrays)
	var m = MeshInstance.new()
	m.mesh = arr_mesh
	
func _process(delta):
	rotate_y(0.5)

I then saved, dragged my Triangle.tscn of this class into the MainScene class to create an instance of the MeshInstance Triangle class in the scene (which then looked fine in the viewport).

I then hit run confidently expecting to see a rotating triangle. Instead I get just a bare bones scene . :frowning: Meh, nothing works first time for a noob it seems.

I tried it with _ready as above and _init and neither method worked. Where am I going wrong? Do I need to add a child node to actually see it?

Thanks in advance!

:bust_in_silhouette: Reply From: DDoop

Whenever you create a node via GDScript, you must add it to the scene tree via:
node_already_in_tree.add_child(the_new_node_you_are_introducing). You can leave out the part before the period if you want to add the node as a child to the node that is running your script.
The draw function is only called on nodes in the scene tree.
EDIT: I looked closer at your code, and I think you would be better served by skipping the var m = MeshInstance.new(). Since the script is already attached to a MeshInstance, it would suffice to simply use mesh = arr_mesh instead of applying the array mesh to a new object. What your code does now is basically create a scene with 2 MeshInstances in it, where one of the MeshInstances just doesn’t have any mesh data.

Great, thank you, got it working. Just removing the instantiation from the MeshInstance (Triangle) script was enough to get it going - without adding the add_child onto the Spatial node.

I suspect - correct me if I’m wrong - that the instantiation happened because I dragged the Triangle.tscn file into the viewport. Which meant I already had a double instantiation and, as you say, the one in the scene was null and the other one with the array wasn’t in the scene.

So I can drag elements in manually or I can code them into the Spatial (or any other class) script. Perfect. One thing, is add_child a static method? Shouldn’t it be self.add_child in the spatial node? Finally, is the class passed in referenced add_child($Triangle), add_child(Triangle) or add_child(“Triangle”)?

Sorry to pester, I’m just trying to get a handle on the language. Thanks again.

DaddyMonster | 2020-07-19 18:42

I personally don’t drag scenes into the viewport, so I don’t really know the behavior you’re describing.
No, it’s not a static function. Any time you call a method without specifying the target (by prefacing the method call with a object.), it’s implicit that you mean self.method(). Writing it either way works, but leaving self out makes the code shorter. Static functions are those which do not require an instance of their owner class to exist, and it’s not possible to add_child() to an object that hasn’t been instantiated.
For a given argument, add_child(argument) expects argument to resolve to a reference to any object that inherits from Node. Spatial is one, MeshInstance also works. Anything you can add to the scene tree from the editor inherits from Node. Instanced scenes also inherit from Node since they are made up of more primitive built-in objects.
I’m not sure what you mean by “is the class passed in referenced.” You can avoid the italicization that’s happening in your posts by surrounding your code in backquotes (located on the same key as your tilde, just below the esc key). This is it:`
$Triangle is functionally identical to get_node("Triangle"). All $ does is offer you a convenient alternative to typing get_node(), so if you’re confused about that method, seek it out in the documentation. It should be on the Node page.

DDoop | 2020-07-19 19:31

That’s made everything crystal clear, thanks again. I’m from a python background where instance variables and local variables are distinguished within methods and you can’t omit self if you want to pass the obj reference id - that was what was confusing me but I’ve got it now. I’m pretty sure dragging and dropping just adds the equivalent of object.add_node(object) somewhere in the background but I’ll script it in future to be explicit.

As for the referencing in arguments, that makes perfect sense - I so wish python had $ although I do think it would be better if get_node passed a first class object rather than a string but it’s fine now I know. I’ve also just rewritten it with SurfaceTool, it’s much easier for a simpleton like me. :slight_smile: I’m really loving this engine, simply amazing. Thanks once more, I’m making great progress now.

DaddyMonster | 2020-07-19 20:16

Congrats on getting SurfaceTool to work, if you check my post history you’ll find I could not get my head around it haha. Glad to help, please mark the question as solved so it gets moved out of the unanswered category.

DDoop | 2020-07-19 20:21