0 votes

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.

Godot version 3.2.3
in Engine by (236 points)

1 Answer

+1 vote
Best answer

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 changecenter ? If not than maybe You should consider using Autoload pattern.

Getnode(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 getnode() like get_node("/root/TMI")

by (5,128 points)
selected by

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

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.