godot: surface material index out of bounds error when instancing model loaded from another thread

Godot version

3.4.beta6

System information

Linux Mint 20.2 Uma base: Ubuntu 20.04 focal GLS3

Issue description

When trying to .instance() a PackedScene which was .load()ed in another thread, I got the following error:

E 0:00:00.748   instance_set_surface_material: Index p_surface = 0 is out of bounds (instance->materials.size() = 0).
  <C++ Source>  servers/visual/visual_server_scene.cpp:730 @ instance_set_surface_material()
  <Stack Trace> Main.gd:15 @ _add_node()

Tested with Godot 3.3, 3.3.1 and 3.3.3 and the same error happens

Steps to reproduce

  1. Open the project
  2. Run the project
  3. Check output

Minimal reproduction project

Here is a minimal project to reproduce the error: godot_test_surfaces_material.zip

The relevant part is the following:

func _ready():
	thread.start(self, "_thread_function")


func _thread_function():
	var packed_scene = ResourceLoader.load("res://tree.tscn", "PackedScene", false)
	call_deferred("_add_node", packed_scene)


func _add_node(packed_scene):
	add_child(packed_scene.instance())

Which produces two errors, since the example model has 2 meshes:

E 0:00:00.748   instance_set_surface_material: Index p_surface = 0 is out of bounds (instance->materials.size() = 0).
  <C++ Source>  servers/visual/visual_server_scene.cpp:730 @ instance_set_surface_material()
  <Stack Trace> Main.gd:15 @ _add_node()
E 0:00:00.748   instance_set_surface_material: Index p_surface = 0 is out of bounds (instance->materials.size() = 0).
  <C++ Source>  servers/visual/visual_server_scene.cpp:730 @ instance_set_surface_material()
  <Stack Trace> Main.gd:15 @ _add_node()

If I change the code to instantiate within the thread itself, no error is shown:

func _ready():
	thread.start(self, "_thread_function")


func _thread_function():
	var packed_scene = ResourceLoader.load("res://tree.tscn", "PackedScene", false)
	call_deferred("_add_instanced_node", packed_scene.instance())


func _add_instanced_node(node):
	add_child(node)

About this issue

  • Original URL
  • State: open
  • Created 3 years ago
  • Reactions: 4
  • Comments: 18 (6 by maintainers)

Most upvoted comments

Relate to https://github.com/godotengine/godot/issues/40954.

PS: You can use gdscript syntax highlighting for code blocks on GitHub. I edited your post accordingly 🙂

(While setting material directly onto Mesh - no error occurs), but for my task i need to use custom materials, I solved this problem by setting material in GeometryInstance -> material_override. Error and black material occurs when i was trying to set in into “material/0”. image

Well, both not work when running in exported iOS project. BUT, both work when running it in editor mode (desktop).

It doesn’t work because the imported resource is not included within the exported PCK. You’ll surely reproduce the same issue if you export the project to a desktop platform and run it.

It seems to happen when preloading scenes with MeshInstances that have both a custom mesh as well as an assigned Material. So, likely a confusion between loading the obj textures along with in editor textures, correct?

I haven’t tested with in-editor shapes, only imported meshes.

If you are importing meshes (mine for instance is obj imported), they will come with a default spatial. It may be transparent on import also. If you are getting these out of bounds errors even when clearing the material, and trying to add a new one, it might not fix it either. Youll have to re_import the mesh again and overwrite (as long as the initial import doesn’t cause the issue, it should fix the error). You might have the transparency issue, but I have a gd script for that on )ready():

func _ready():
	for c in mesh.get_surface_count():
		var material = mesh.surface_get_material(c)
		material.albedo_color.a = 255
		material.flags_transparent = false
		set_surface_material(c, material)
		var material2 = SpatialMaterial.new()
		material2.albedo_color.a = 255
		material.flags_transparent = false
		set_surface_material(0, material2)

Hopefully that will help a little maybe. Just make sure that you do not add a material from the node, just have the imported mesh handle it. Attach this script to ANY “MeshInstance” you use that brings up that error