0 votes

The situation:

I've got a 3d model with many meshes which I originally imported with glTF (with materials) and set as a scene. I decided to change one of the many MeshInstances so, to avoid starting from scratch, I made a new model for the mesh in question, exported from blender as a obj and added that as a mesh (ArrayMesh) to the relevant MeshInstance. The new mesh has three surface materials. I made new materials in Material Maker, added them manually and converted them to ShaderMaterial.

The issue:

Even though the mesh's surface materials are ShaderMaterial in the editor (and in Remote during runtime) and are rendered as the desired ShaderMaterial in the game, when addressed in code it returns as a SpatialMaterial.

That is to say: print(obj.mesh.surface_get_material(0)) returns [SpatialMaterial:2061]

Obviously, obj.mesh.surface_get_material(0).set_shader_param("foo", true) throws an error, no function set_shader_param on SpatialMaterial.

I'm certain I'm addressing the right object.

Remedies tried:

Reimporting the mesh / making a new MeshInstance node / making the shader material unique and saving it. It always remains a Spatial when addressed in code but appears as Shader in editor.

Is either the .mtl or .glTF file somehow acting in the background here but only in code?

Anyone know what's going on?

Godot version 3.2.3
in Engine by (817 points)

1 Answer

+1 vote
Best answer

I had the same problem and this was the only google link that mentioned it.

So I think that the mesh is instanced from the file; if you change one of the materials, quit godot and then load back the scene you'll see the materials go back to what they where.

The solution is to add a material to the MeshInstance, NOT the Mesh. If you import a mesh, then the properties window for me shows:

MeshInstance -> Mesh -> Surface1, Surface2 etc

You can leave those surfaces alone, instead, if we want to change surface2m we need to add:

Meshinstance -> Material -> 2

Again, all in the properties tab. Now if you write:

$name_of_node.get_surface_material(index_of_material)

Will indeed return a ShaderMaterial. Also, the shader material will override what material is in the Mesh.

Hope this helps somebody!

by (46 points)
selected by

Nice. I'm a little embarrassed I didn't figure this out for myself, I ended up reimporting the entire mesh. Still, great advice for someone googling the issue in the future.

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.