0

I'm making a 2.5D tower defense game with bloons in Godot. (All code and scenes are on my github). (Also I fixed my git so the repo is working now) My Bloon scene consists of a Node3D and a Sprite3D for the Bloon, and when I instantiate the Bloon (in code) the Node3D and Sprite3D are in the scene tree, but it doesn't show the sprite.

I tried changing the sprite after instantiating the scene, but still nothing. I also tried hiding all other objects, but still, nothing. J was expecting that the Bloon sprite would show at 0,0,0 but it didn't.

  • I don't see any `Sprite3D` in your Bloon scene: https://github.com/SupaSibs/bmc2/blob/b29f097afcc0e7148e5301303122d65f00533e88/sprites/bloons/bloon.tscn - I don't see code initialize it either, instead I see broken code: https://github.com/SupaSibs/bmc2/blob/b29f097afcc0e7148e5301303122d65f00533e88/getsize.gd - Please add the relevant information to the question, you can [edit](https://stackoverflow.com/posts/76724581/edit) it. – Theraot Jul 20 '23 at 05:37
  • fridge i forgot to commit and my pc is away rn – SUPA Siblings Jul 20 '23 at 22:16
  • sry bout that theraot – SUPA Siblings Jul 20 '23 at 22:16
  • Fixed @Theraot, my git was broken – SUPA Siblings Jul 21 '23 at 17:22

2 Answers2

1

It appears I'm writing this as you are also fixing this... This is the version of the code I took:

bloon.gd

extends Node3D
@export var resistances := []
@export var texturePath := "res://sprites/bloons/Red.png"
# Speed is in red bloons / second
@export var speed := 1
#For fortified leads
@export var health = 1
@export var children := []
# TODO
# add moving across map
func _ready():
    var sprite = $Sprite
    sprite.texture = load(texturePath)
    pass



func _process(delta):
    pass

Here you load the texture on _ready:

sprite.texture = load(texturePath)

Now, modifying the value of texturePath afterwards won't change the texture, because there is no reason for _ready to run again.


There is a pattern that would work in this case, you need a setter, and an update function:

@export var texturePath := "res://sprites/bloons/Red.png":
    set(mod_value):
        if texturePath == mod_value:
            return

        texturePath = mod_value
        if is_inside_tree():
            update()
        else
            request_ready()


func _ready() -> void:
    sprite = $Sprite
    update()


func update() -> void:
    sprite.texture = load(texturePath)

So, when you modify the texturePath, either the Node3D is or isn't in the scene tree.

If it is in the scene tree, then you can go ahead an load the texture and set it to the sprite.

If it isn't then we request to run _ready when it enters the scene tree again (with request_ready) and in _ready you also go ahead and load the texture and set it to the sprite.

Since the "load the texture and set it to the sprite" part is the same in both cases, we have it extracted to an update method and call it from both places.

Theraot
  • 31,890
  • 5
  • 57
  • 86
0

I found the answer: turns out you need to use preload() instead of load().

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83