Instancing multiple nodes, but all share the last node's texture

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

Hi, I’m really enjoying Godot so far and am porting a game over from Unity.

I’ve built a Main scene and a scene called Letter. The Letter scene contains just a MeshInstance (Cube) and a default texture. From within the Main scene’s script, I instance two copies of the Letter scene and one texture to the first instance, and another texture to the second instance.

Problem is, when I run the Main scene, it instantiates two of the Letter scene objects but they both share the last texture, instead of their own texture. I hope I’m explaining my issue properly.

Here’s the code from Main.gd:

extends Spatial

export (PackedScene) var Letter

# Called when the node enters the scene tree for the first time.
func _ready():
	spawn_letter("W", Vector3(0.0, 1.0, 0.0))
	spawn_letter("O", Vector3(1.0, 1.0, 0.0))
	
func spawn_letter(letter: String, position: Vector3):
	var letterNode = Letter.instance()
	var box = letterNode.get_node("MeshInstance")
	var texture = ImageTexture.new()
	texture.load("res://art/letters/set1/" + letter + ".png")
	box.material_override.albedo_texture = texture
	
	letterNode.translate(position)
	add_child(letterNode)

From the code above, it should load a texture from path “res://art/letters/set1/W.png” and a texture from path “res://art/letters/set1/O.png”

If I run it with just the first spawn_letter() call, the W texture loads properly. You’d think that this would create two blocks, one with the texture W and the next with the texture O, but they’re both using the texture O.

Anyone here want to help me with what looks like a scoping issue?

Thank you!

:bust_in_silhouette: Reply From: Mike Trevor

You’re gonna have to make your material unique by duplicating it. I had a similar problem once when I wanted my MeshInstances to fade separately, however Godot makes them have the same material with the same state, with one of the instances fade instantly like popping a bubble.
enter image description here

I’m not sure how to do it in your case, but here’s a similar question with some answers that could help you.

After some rejiggering of the code, and using duplicate() to make copies of the Mesh material, this works!

It’s not as nice as I’d like, but we can’t have everything :slight_smile: Thanks a bunch!

Here’s what I did in the cube’s script:

extends MeshInstance

func setup(letter: String):
    print("spawning letter " + letter)
    var material = get_surface_material(0)
    var texture = ImageTexture.new()
    texture.load("res://art/letters/set1/" + letter + ".png")
    material.albedo_texture = texture
    set_surface_material(0, material.duplicate())

jeku | 2020-04-03 02:53