Use this space for questions related to what you're learning. For any other type of support (website, learning platform, payments, etc...) please get in touch using the contact form.
This one was a bit toughmiserly-dugongYesterday I happily said I finally understood setter functions! but today was a tough reality check. I know nothing! But I think I get it a little more now. Hopefully I won't bite my own words tomorrow again...10Feb. 20, 2025
typo in func collect_item()CGQQLI think you want:
```gdscript
var is_audio_longer := _audio_stream_player.stream.get_length() > _animation_player.get_current_animation_length()
```
not
```gdscript
var is_audio_longer := _audio_stream_player.stream.get_length() > _animation_player.current_animation.length()
```
in func collect_item().
current_animation.length() returns the length of the string of the animation name.
10Feb. 15, 2025
why do you set item 2 times?silent-meerkatwhy do we do item = value in the set_item func and then set_item(item) in _ready?
dosnt it do the same thing?
dosnt it just set value as item and then back item as value?
10Feb. 15, 2025
body_entered not workingoliver_gzzHey there, it seems that I got stuck in the most simple thing: the body_entered signal, I've reduced the code in the PickUp scene to see if nothing was messing with the signal, but still, is not working when the player is touching the pickup element.
here's the code:
**`@tool`**
**`class_name PickUp extends Area2D`**
**`@export var item: Item = null: set = set_item`**
**`@onready var _pickup_sprite : Sprite2D = %Sprite2D`**
**`@onready var _sound_player : AudioStreamPlayer2D = %AudioStreamPlayer2D`**
**`# Called when the node enters the scene tree for the first time.`**
**`func _ready():`**
**` set_item(item)`**
**` body_entered.connect(func(body: Node2D):`**
**` if body is Player:`**
**` print("touching element")`**
**` )`**
**`func set_item(value:Item):`**
**` item = value`**
**` if _pickup_sprite != null:`**
**` _pickup_sprite.texture = item.texture`**
**` if _sound_player != null:`**
**` _sound_player.stream = item.sound_on_pickup`**
10Feb. 11, 2025
Is it possible to put a particle effect in a resource?EndeiosI tried to add a GPUParticles2D to the item, but I got that
`Parse Error: Node export is only supported in Node-derived classes, but the current class inherits "Resource".`
So i just put the color for the time being :)
Is it at all possible to put a particle effect in a resource? Or it is just a good idea to keep it in the pick up?
Or should I just get the "interesting" values from the resource as strings or numbers and apply them on _ready?
```gdscript
class_name Item
extends Resource
## Texture to display for this item
@export var texture:Texture2D = null
## Color to use for particles
@export var color:Color = Color.WHITE
## Sound to play on pickup
@export var pick_up_sound:AudioStream = null
func use(player:Player)->void:
pass
```
```gdscript
class_name HealingItem
extends Item
@export var healing_amount:int = 0
func use(player:Player)->void:
player.health +=healing_amount
```
```gdscript
@tool
class_name PickUp
extends Area2D
@export var item:Item = null
@onready var sprite: Sprite2D = %Sprite
@onready var collision_area: CollisionShape2D = %CollisionArea
@onready var audio_player: AudioStreamPlayer = %AudioPlayer
@onready var animation_player: AnimationPlayer = %AnimationPlayer
@onready var particles: GPUParticles2D = %Particles
var _picked_up : bool = false
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
if item != null:
sprite.texture = item.texture
particles.modulate = item.color
play_floating_animation()
if Engine.is_editor_hint():
return
body_entered.connect(pick_up_item)
func pick_up_item(entered:Node):
if entered is not Player:
return
if not _picked_up:
_picked_up = true
item.use(entered)
audio_player.stream = item.pick_up_sound
audio_player.play()
animation_player.play("wobble")
var tween := create_tween()
tween.tween_property(sprite, "modulate:a", 0, 1.0 )
set_deferred("monitoring",false)
particles.emitting = true
particles.one_shot = true
audio_player.finished.connect(func ():
queue_free()
)
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta: float) -> void:
update_configuration_warnings()
if Engine.is_editor_hint():
return
func _get_configuration_warnings() -> PackedStringArray:
var warnings :Array[String]=[]
if item == null:
warnings.append("You need to specify an item resource")
return warnings
func play_floating_animation() -> void:
var position_offset := Vector2(0, 4)
var animation_duration := randf_range(0.5,1.5)
var tween := create_tween()
tween.set_trans(Tween.TRANS_SINE)
tween.tween_property(sprite, "position", position_offset, animation_duration)
tween.tween_property(sprite, "position", -1 * position_offset, animation_duration)
tween.set_loops()
```20Feb. 10, 2025
Invalid assignment of property or key 'texture' with value of type 'CompressedTexture2D' ....SpookyDoomSo my script ended up pretty close to the reference one but I ultimately ended up having one error on starting the game I could not figure out why it happened. The setter function in my `pickup.gd`file looked like this:
```gdscript
func set_item_type(new_item : Item) -> void:
item_type = new_item
if Engine.is_editor_hint():
update_configuration_warnings()
if new_item.item_texture != null:
# set the new item texture
item_sprite.texture = new_item.item_texture
# ... rest of code
```
My idea was that `if new_item.item_texture != null` should check if the resource actually has a texture assigned in the first place before assigning anything to the sprite texture (same for the AudioStream).
On starting the game I get this error, though:
> *Invalid assignment of property or key 'texture' with value of type 'CompressedTexture2D' on a base object of type 'Nil'.*
You, on the other hand, simply check if there is an ItemSprite and an AudioStream to assign something to, right?
Why do I get that error and why do you check only for the existence of the destination nodes instead?10Feb. 07, 2025
my solutions, not sure about setterSootyAfter seeing the solution at the end of the lesson, why is the setter used? the pickup is setup and you assign a sprite, sound etc in the main game scene so its not going to change via code? is this simply for displaying the item in editor with the @tool function? This was my code which didn't use the setter
class_name Pickup extends Area2D
@export var item : Item = null
@onready var sprite_2d: Sprite2D = %Sprite2D
@onready var audio_stream_player_2d: AudioStreamPlayer2D = %AudioStreamPlayer2D
func _ready() -> void:
sprite_2d.texture = item.texture
audio_stream_player_2d.stream = item.item_pickup_sound
body_entered.connect(func(body : Player)-> void:
if body is Player:
item.use(body)
audio_stream_player_2d.play()
set_deferred("monitoring", false)
audio_stream_player_2d.finished.connect(func() -> void:
queue_free()
)
)10Feb. 05, 2025
My code + questionsmilk_manHere is my code
item.gd:
```gdscript
class_name Item extends Resource
@export var texture: Texture2D
@export var sound: AudioStream
# virtual function, exists to be overridden
func use(player: Player) -> bool:
return true
```
healing_item.gd:
```gdscript
class_name HealingItem extends Item
@export var healing_amount := 1
func use(player: Player) -> bool:
var is_health_full: bool = false
if player.current_health == player.max_health:
is_health_full = true
return is_health_full
player.current_health += healing_amount
return is_health_full
```
pickup.gd:
```gdscript
@tool
class_name Pickup extends Area2D
@export var item: Item:
set = set_item
@onready var _sprite: Sprite2D = %Sprite2D
@onready var _audio: AudioStreamPlayer2D = %AudioStreamPlayer2D
var tween: Tween
func _ready() -> void:
if Engine.is_editor_hint():
return
set_item(item)
play_floating_animation()
body_entered.connect(func(body_that_entered: Node2D) -> void:
if body_that_entered is Player:
# check if player health is full, if not, run code
if item.use(body_that_entered) == false:
_audio.play()
if tween != null:
tween.kill()
play_disappearing_animation()
# another way of handling playing audio and queue_free, different with bullets
set_deferred("monitoring", false)
await _audio.finished
queue_free()
)
func set_item(value: Item) -> void:
item = value
if _sprite != null:
_sprite.texture = item.texture
if _audio != null:
_audio.stream = item.sound
func play_floating_animation() -> void:
tween = create_tween().set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_SINE)
var duration := randf_range(0.8 , 1.2)
tween.set_loops()
tween.tween_property(_sprite, "position:y", -15, duration)
tween.tween_property(_sprite, "position:y", 0, duration)
func play_disappearing_animation() -> void:
tween = create_tween().set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_SINE)
tween.tween_property(_sprite, "scale", Vector2.ZERO, 0.3)
```
I used tweens for the animation instead of AnimationPlayer, bc I thought the animations were simple enough. Also I changed the use() function signature to return a bool and also check within the function if player current health is equal to max health. If it is, the function returns false, thus the player is unable to pickup the item.
Now here are my questions:
- Is the way I implemented the logic (to prevent the player from picking up the healing item if is current health is equal to max health) good enough? How would you do it? I thought about emitting a signal, but it just wouldn't work. Also thought of checking player current health with max health within the pickup script instead, but that would in turn make the pickup scene less scalable, for example if we were to use a Speed Item
- Now bc in my script, the function `use()` now returns a bool, I was afraid that I couldn't just call the function anymore, that I had to store or do something with the returned value, but to my surprise you can still just call `item.use(body_that_entered)` no problem. I used to program a bit in C, and if I remember correctly (could be wrong), that if a function wasn't void, you couldn't just call it, you had to do something with the returned value. Does Gdscript differ in that regard?
- Last question. the item variable is of type **Item**, but can still accept objects of type **HealingItem**. And if we do assign a HealingItem object, we have access to properties shared by both Item and HealingItem. What confuses me is the following, our item variable can't access the healing_amount property of HealingItem, which makes sense, but we can access the overriden use() function from HealingItem? How does that work?
40Feb. 04, 2025
Suggestion: Scene SetupNeepersCan you please also provide the scene set up? I am confused on whether I should be setting up the pickup item directly in the item scene or if I should be adding the pickup scene to my main game scene and setting it there?10Jan. 31, 2025
Resources, a bit confusingPurpleSunriseHello,
I still don't understand resources quite well. I managed to make everything work but I want to make sure I got the meaning of using resources right. First my code:
```gdscript
@tool
class_name Pickup extends Area2D
@export var item : Item = null : set = set_item
@onready var sprite_2d: Sprite2D = %Sprite2D
@onready var audio_stream_player: AudioStreamPlayer = %AudioStreamPlayer
# Called when the node enters the scene tree for the first time.
func _ready() -> void:
set_item(item)
if Engine.is_editor_hint():
return
body_entered.connect(func(body : Node)->void:
if body is Player:
item.use(body)
set_deferred("monitoring", false)
audio_stream_player.play()
var tween := create_tween()
tween.tween_property(sprite_2d,"scale", Vector2(0,0), 0.3)
await audio_stream_player.finished
queue_free()
)
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(_delta: float) -> void:
pass
func set_item(pickup : Item)->void:
item = pickup
if sprite_2d != null:
sprite_2d.texture = item.display_image
if audio_stream_player != null:
audio_stream_player.stream = item.pickup_sound
```
I created a pickup scene. This pickup item could be anything right? It could be a speed boost, a healing item, a power up.
You can chose what type of item it will be from the dropdown menu in the inspector, and so far I think I got it.
I make a resource that extends from the blueprint Item resource and override the `use()` function and give that pickup properties like speed boost amount, power boost amount etc.
In other words, Item resource is just a blueprint that I will never use on a pickup, I would use resources created from that blueprint. And any pickup type resource extends from that blueprint and can have new functions, properties etc.
Then you can put a bunch of pickup items in the scene and you can set the type of pickup for each item choosing the resource from the dropdown menu. Then you need to set up each pickup's texture and sound and other properties (unless you don't duplicate an already set one i guess?). But since every items runs from one script, all the items have to be have functions in common to work as it is now. For example all pickups have to have a use() function for example? Or does it mean that in that pickup script, once I have many items, I'll have to check if an item is a certain type and them call certain functions specific for that item?
Also, in this case, since I know that more or less all the audio length are longer than the animation of disappearing I just wait the audio to finish before freeing the item, but I guess if I had a large amount of item, it would be better to check both the animation and the audio to be finished before freeing the item?
I also tried to use to @tool annotation to update the sprite in the editor, but I had to reload the scene every time to make it update. Is it normal or maybe I set something wrong?
Lastly, something about monitoring and monitorable. Monitoring basically means that the area2d detects things and run signals like body_entered etc. Monitorable means that let other physics objects to detect the area and run signals they have in the script? Sorry for the poor explanation but I hope it makes sense.
I am sorry for the very long confused questions, I hope I can get some help with this because it looks like such a powerful tool I would like to learn how to use! I think I am almost there but I need to understand the purpose a bit more!
thank you!70Jan. 26, 2025
no sound is played when I collect my itemsPixAngelAll is in the title. I still have the same code as you :
```gdscript
func set_item(value : Item):
item = value
if sprite_2d != null and item != null:
sprite_2d.texture = item.texture
if audio_stream_player_2d != null:
audio_stream_player_2d.stream = item.so
```
I added in my func _ready connection :
```gdscript
body_entered.connect(func(body : Node) -> void:
if body is Player:
item.use(body)
audio_stream_player_2d.play()
queue_free()
)
```
Did i miss something?80Jan. 16, 2025
How can I make the sprite change in the editor?DMKAs in your questions and troubleshooting, even if you change the texture property of the healing item, it will not be changed in the editor.
But creating a setter function in the HealingItem script is impossible, so how should I go about doing this?10Jan. 15, 2025
Found a typoDMK> For a single kind of item, for example, if you exclusively make healing items in your game, **exploring** properties like which image...
exploring -> exporting
Also, a space is missing in:
> Notice how the `use()` function is [empty]() in the base `Item` resource. This is because the base item resource only defines a generic **[type](https://school.gdquest.com/glossary/type)and.....**10Jan. 15, 2025
Challenge idea: consume health items only when they actually heal the playerHardRockWith a minor modification to the `use()` function (there are probably other ways as well) this is an easy change to make and adds a bit of extra quality of life for the player, since they won't have to avoid healing items when they are at max HP.10Jan. 05, 2025
Crash due to animationram876Hello! I've encountered an error that I don't understand. I added an idle animation for the pickup sprite. If you add pickup to the level, then everything works fine. But after restarting, the editor crashes if you switch to this scene. I realized that the problem with enabling animation was only after much trial and error. When running from the command line, it outputs the following information:
```gdscript
CrashHandlerException: Program crashed with signal 11
Engine version: Godot Engine v4.3.stable.official (77dcf97d82cbfe4e4615475fa52ca03da645dbd8)
Dumping the backtrace. Please include this when reporting the bug to the project developer.
[1] error(-1): no debug info in PE/COFF executable
[2] error(-1): no debug info in PE/COFF executable
[3] error(-1): no debug info in PE/COFF executable
[4] error(-1): no debug info in PE/COFF executable
[5] error(-1): no debug info in PE/COFF executable
[6] error(-1): no debug info in PE/COFF executable
[7] error(-1): no debug info in PE/COFF executable
[8] error(-1): no debug info in PE/COFF executable
[9] error(-1): no debug info in PE/COFF executable
[10] error(-1): no debug info in PE/COFF executable
[11] error(-1): no debug info in PE/COFF executable
[12] error(-1): no debug info in PE/COFF executable
[13] error(-1): no debug info in PE/COFF executable
[14] error(-1): no debug info in PE/COFF executable
[15] error(-1): no debug info in PE/COFF executable
[16] error(-1): no debug info in PE/COFF executable
[17] error(-1): no debug info in PE/COFF executable
[18] error(-1): no debug info in PE/COFF executable
[19] error(-1): no debug info in PE/COFF executable
-- END OF BACKTRACE --
```
And sometimes, after several restarts, the scene starts, but the idle animation does not start, and the following message is constantly printed on the command line:
```gdscript
ERROR: Condition "!has_animation(p_name)" is true.
at: make_animation_instance (scene/animation/animation_mixer.cpp:1909)
```
My pickup script is almost identical to yours.40Dec. 31, 2024
Bullet Boosterram876Hello! I couldn't figure out how to make a booster that increases the damage for bullets. Bullets are created dynamically on the stage and I do not know how to write the use() function in this case. I tried writing `var bullet :=player.get_node("WeaponPivot/WeaponAnchor/Weapon")` in the booster. And storing the bullet in a variable in weapon. But I couldn't get this variable in the booster. What should I do in these situations?50Dec. 30, 2024
Something odd about the example provided in the lessonCptnNuggetsHi there, a question related to your example about the use of ressources. You propose this code :
```gdscript
class_name Pickup extends Area2D
@export var item: SpeedItem = null
```
But that means constraining the item variable to the SpeedItem class. Doesn't that goes against the design pattern you propose ? Shouldn't it be this instead :
```gdscript
class_name Pickup extends Area2D
@export var item: Ressource = null
```
I'm curious if I misunderstood something or if it's just a typo ?
Furthermore, to enhance readability (for me, not saying it's better ^^ just the way my mind works), would the following be possible ? Create a class "Item extends Ressource" which would implement properties and functions shared between all items (ie, in your example, use() and display_image) with properties set to null and functions to "pass".
Then, for each item type, the class would extend the "Item" class instead of the general "Ressource" one, and overload the functions as needed ? Would this be a valid approach ? Would there be drawbacks ? The 2 adantages I see are that this Item class would inform on necessary functions/properties when creating a new Item further down the line, plus the Pickup class would then be more readable like this :
```gdscript
class_name Pickup extends Area2D
@export var item: Item = null
```40Dec. 20, 2024
Did you used the set_deferred() in pickup script, because the monitoring property is related to physics/collision?◆ LPI was confused because we didn't use anything in the _physics_process() here.
But it did helped in stopping the player character from unintentional healing because it could keep entering the pickup's area while the pickup audio is playing.40Dec. 18, 2024
Update texture in editor via @toolKetan```gdscript
@tool
extends Area2D
class_name Pickup
@export var item: Item = null: set = set_item
@onready var sprite_2d: Sprite2D = $Sprite2D
@onready var audio_stream_player: AudioStreamPlayer = $AudioStreamPlayer
```
```gdscript
func _ready() -> void:
set_item(item)
body_entered.connect(func(body: Node2D) -> void:
if body is Player:
set_deferred("monitoring", false)
item.use(body)
queue_free())
func set_item(value: Item) -> void:
item = value
if sprite_2d != null:
sprite_2d.texture = item.texture
if audio_stream_player != null:
audio_stream_player.stream = item.pickup_sound
```90Dec. 17, 2024
@onready variables being nullnasty-beeSomething strange just happened to me. Although my scene, script and resources were setup correctly (I double checked and even compared to the solution), Godot gave me an error ("invalid access to property or key 'texture' on a base object of type 'Nil'). I know this means that the @onready variable wasn't referring properly to the sprite, but I could not figure out what the issue was.
I ended up restarting the engine, and somehow the issue just fixed itself! The script that was giving me an error before the restart was now working perfectly, without changing anything.
This brings me to ask a few questions:
1) I noticed that in your script, you check if the variables are null in the ready function. At first I didn't understand why you would do this since the ready function is supposed to run only when all the children are ready. Is the line added to prevent errors like the one I had or is there another reason?
```gdscript
if _sprite_2d != null:
_sprite_2d.texture = item.texture
if _audio_stream_player != null:
_audio_stream_player.stream = item.sound_on_pickup
```
2) It's not the first time restarting the engine has solved an issue for me. It seems I'm not the only one, as I've seen plenty of people on Reddit suggesting restarting as a solution to encountering a strange bug. This honestly scares me a little. Are my players also going to experience similar issues and need to restart the game, or are these bugs only present while I'm developing the game and playtesting?20Dec. 15, 2024
Using @tool to update the spritePaulI fancied having a go with using `@tool` to get the sprite to update in the editor. I couldn't really remember how this went, and with a bit of looking I determined you have to use a setter function to force the update in the editor. But I was really struggling with the syntax or how to go about actually doing it.
I'm thinking you'd need the setter function on the `item` resource (since this is what we are setting the new properties in). Something like:
```gdscript
@export var item: Item = null : set = set_item_properties
```
However `item` has a number of properties (`healing_amount`, `item_visual`, `item_sound` in my case as it's the healing item). I couldn't work out how I write a setter function that can take multiple properties, so far I think we've only handled setters on say an `int`, where you know what will be expected. I tried a few things which all just resulted in errors.90Dec. 14, 2024
health bar doesn't update immense-swallowHi, I followed the code, but I'm unsure why my health bar only updates when attacked by the mob but not when picking up items.I feel confused about the Setter function. Could you explain this part in more detail?
And is it possible to reduce the time gap between the player's death and reloading the game?Thank you.20Dec. 10, 2024
How to make it so the Healing Pickup resource has pre-defined texture.DargorWith this format, you can set the texture for the Sprite node in the inspector. But how do I make it so that the Healing Pickup always uses the same texture, so that I don't have to choose the texture every time I assign it to the Pickup scene? I tried assigning the texture to a variable inside the Health Pickup script (var image = preload("texture location") and then assigning it to the texture var in the ready function (texture = image) so that the set_item function in the Pickup scene assigns the image, but it doesn't work. 40Dec. 02, 2024
Lesson Q&A
Use this space for questions related to what you're learning. For any other type of support (website, learning platform, payments, etc...) please get in touch using the contact form.