Why do I get this error: "attempt to call function 'set_surface_material' in base 'null instance' on a null instance"?

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

Hello,
I’m trying to change a material of one MeshInstance. Here is the code where the node is created, basically a MeshInstance with two surfaces, where at the end of the code I created a function to change the material of one of them (there is the error):

class_name Tile
extends Spatial

var N : int
var iL : float
var oL : float


func _init(N=6, iL=0.9, oL=1):
	self.N = N
	self.iL = iL
	self.oL = oL


func _ready():
	_generate_tile(N, iL, oL)


func _generate_tile(N, iL, oL):
	# generates the MeshInstance for the Tile
	# N : int = number of corners
	# iL : float = inner radius
	# oL : float = outer radius
	
	# MeshInstance for the Mesh
	var meshInstance : MeshInstance
	# Mesh for the tile
	var mesh : Mesh
	
	meshInstance = MeshInstance.new()
	meshInstance.name = 'TMI'
	
	# angle between the position vectors of two consecutive vertices of the hexagon
	var angle : float = 2*PI/N
	
	# pivot points
	var polyVertices : PoolVector3Array = PoolVector3Array([
	Vector3.BACK*iL,
	Vector3.BACK*oL
	])
	
	# generate verteces, first inner ones, then outer ones
	for i in range(1, N):
		polyVertices.append(polyVertices[0].rotated(Vector3.UP, -i*angle))
		polyVertices.append(polyVertices[1].rotated(Vector3.UP, -i*angle))
	
	# SurfaceTool for the inner polygon
	var iSurfaceTool : SurfaceTool = SurfaceTool.new()
	# SurfaceTool for the borders of the polygon
	var oSurfaceTool : SurfaceTool = SurfaceTool.new()
	
	iSurfaceTool.begin(Mesh.PRIMITIVE_TRIANGLES)
	oSurfaceTool.begin(Mesh.PRIMITIVE_TRIANGLES)
	
	for i in range(2*N-2):
		if i%2 == 0:
			iSurfaceTool.add_vertex(Vector3.ZERO)
			iSurfaceTool.add_vertex(polyVertices[i])
			iSurfaceTool.add_vertex(polyVertices[i+2])
			
			
			oSurfaceTool.add_vertex(polyVertices[i])
			oSurfaceTool.add_vertex(polyVertices[i+1])
			oSurfaceTool.add_vertex(polyVertices[i+3])
			
			oSurfaceTool.add_vertex(polyVertices[i])
			oSurfaceTool.add_vertex(polyVertices[i+3])
			oSurfaceTool.add_vertex(polyVertices[i+2])
	
	
	iSurfaceTool.add_vertex(Vector3.ZERO)
	iSurfaceTool.add_vertex(polyVertices[2*N-2])
	iSurfaceTool.add_vertex(polyVertices[0])
	
	iSurfaceTool.generate_normals()
	
	
	oSurfaceTool.add_vertex(polyVertices[2*N-2])
	oSurfaceTool.add_vertex(polyVertices[2*N-1])
	oSurfaceTool.add_vertex(polyVertices[1])
	
	oSurfaceTool.add_vertex(polyVertices[2*N-2])
	oSurfaceTool.add_vertex(polyVertices[1])
	oSurfaceTool.add_vertex(polyVertices[0])
	
	oSurfaceTool.generate_normals()
	
	
	mesh = iSurfaceTool.commit()
	mesh = oSurfaceTool.commit(mesh)
	meshInstance.mesh = mesh
	
	meshInstance.set_surface_material(1, MATERIALS.dict[1])
	
	add_child(meshInstance, true)


func _change_center(key):
	get_node('TMI').set_surface_material(0, MATERIALS.dict[key])

I instance this node in the scene via:

extends Spatial


func _ready():
	var tile = Tile.new()
	tile._change_center(2) # HERE IS THE PROBLEM
	add_child(tile, true)

MATERIALS contains a dictionary with the materials. I get the error when I try to change the material of one of the surfaces. I think that the is because get_node('TMI') doesn’t give the MeshInstance child.

:bust_in_silhouette: Reply From: Inces

The way this error goes it sounds like the missing instance is node TMI itself. Are You sure TMI is ready at the moment of first calling _change_center ? If not than maybe You should consider using Autoload pattern.

Get_node(TMI) indicates, that it must be a child of your Tile node. If it is not, than it will throw the same error - null instance. If it is not supposed to be child of Tile, than You need to insert whole hardcode path into get_node() like get_node(“/root/TMI”)

I changed to:

extends Spatial


func _ready():
    var tile = Tile.new()
    add_child(tile, true)
    tile._change_center(2) # I changed the order

And it works. If I don’t want to change this piece of code, then it works if I call _generate_tile(...) in _init instead of _ready. And here is the issue I believe, when _ready is called is when I add the node to the main scene, so TMI doesn’t exist yet because originally _generate_tile was called in _ready

abelgutierrez99 | 2021-02-23 08:41