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.
helpapt-mooseIn the code reference wand.gd, extends Node3D? Isn't it marker3D?And why does my fireball have an offset to the mouse,Even if I set max_random_angle to 0, I still have that offset.10Dec. 28, 2024
Setter functionsubstantial-tarsierI'm struggling to understand why it's better to use setter functions
Can you better illustrate why one is best practice vs the other?
If I have a chef object with a function
```gdscript
func make_pizza():
pizza.topping = cheese
```
vs
```
pizza.set_topping(cheese)
```10Dec. 04, 2024
Scaling a collision shape: Is it ok?KorielFollowing the second challenge here at the end of the lesson (making the fireballs grow after they've been shot), when we scale the projectile, we are also scaling the collision shape itself.
I had read that we should never scale collision shapes since that messes up with the physics system, so I guess we're only doing it here in the context and for the sake of this practice, so it doesn't get too complex?
Because otherwise, we would need to manually resize the radius of the collision shape in sync with the scaling of the "visuals" themselves instead, right?10Nov. 09, 2024
The bullet is not pointing move in the direction the character facesangelic-lorisHi,
I've following L7. Coding the shooting mechanic, and I got the fireball spawn from the wand's pivot point but it is not move in the direction the character faces.
so the bullet always go to -z position, any pointer on how I can debug for this ?
Thanks50Oct. 17, 2024
projectile.global_transform = global_transformhigh-tarsieri dont quite understand what exactly happens here , you state that the projectile gets the position , scale and rotation of the wand , but doesnt that make the projectile stay in place? since the wand is standing still and not moving? (its obviously not but i dont understand why )20Oct. 04, 2024
Can't figure out L7.P1 ChallengeBrain Siege Gameworks```gdscript
extends Node3D
@export var bullet_scene: PackedScene = null
@export_range(2.0, 40.0, 0.1) var max_range := 12.0
@export_range(5.0, 100.0, 0.1) var max_bullet_speed := 25.0
# Add an exported variable to control the fire rate of the wand.
@export_range(0.01, 100.0, 0.01) var fire_rate := 8.0 : set = set_fire_rate
# Use the timer node to control the attack cooldown, based on the fire rate.
@onready var timer: Timer = %Timer
func set_fire_rate(rate) -> void:
fire_rate = clamp(rate, 0.01, 100.0)
if timer == null:
return
timer.wait_time = 1.0 / rate
pass
func _ready() -> void:
set_fire_rate(fire_rate)
pass
func _physics_process(_delta: float) -> void:
# Check if the player is pressing the shoot button and the weapon is ready to fire.
# If so, shoot a bullet.
if Input.is_action_just_pressed("shoot") and timer.is_stopped() == true:
shoot()
func shoot() -> void:
var bullet := bullet_scene.instantiate()
# Add the bullet as a sibling of the weapon's owner so that it moves independently.
owner.add_sibling(bullet)
# Set the bullet's initial position and rotation to match the weapon's.
bullet.global_transform = global_transform
# Apply the bullet's speed and range based on the machine gun's properties.
bullet.speed = max_bullet_speed
bullet.max_range = max_range
timer.start()
#help i can't exit this code block.
#Either way, this is my attept at solving the challenge. However the bullet only shoots a
#single time despite supposedly starting the timer in shoot()
```30Sep. 14, 2024
Why is the fire rate bound by range and clamped?authorized-scorpionin the wand script the fire rate is limited by @export_range and in the setter function the fire rate is clamped. This appears redundant to me and like it might conflict if set differently. What's the reasoning of setting a range for fire_rate and clamping new_fire_rate? Would variables be a better practice (larger project consideration) to ensure they don't conflict and are set with the same parameters?
`@export_range(0.1, 20.0, 0.05) var fire_rate: float = 3.0: set = set_fire_rate`
`fire_rate = clamp(new_fire_rate, 0.1, 20.0)`
10Sep. 13, 2024
Constants in Projectile and Wand Scriptauthorized-scorpionTrying to find my error and came across these in the Code Reference lines. Am I missing where/when these were added in the scripts or are they not supposed to be in there? I can't find the script(s) when searching the FileSystem...
in the Projectile_3d.gd script this line:
**`const ProjectileSkin3D := preload("projectile_skin_020.gd")`**
in the wand.gd script this line:****
**`const** **Projectile3D := preload("../projectile/projectile_020.gd")`**10Sep. 13, 2024
L7.P1 - Var Projectile 3D vs Var Node 3DMoKTHello, I'm curious why we didn't use "Projectile3D" for the var bullet in L7.P1, and used "Node3D" in the shoot().
I'm guessing there's a gap in my knowledge, I initially removed the Node3D and tried to use the following in the practice:
```gdscript
func shoot() -> void:
var bullet: Projectile3D = bullet_scene.instantiate()
```
instead of the correct answer:
```gdscript
func shoot() -> void:
var bullet: Node3D = bullet_scene.instantiate()
```
Is it just purely how we chose to name the projectile class_name in the projectile_3d.gd script in lesson vs no name in bullet.gd script in the practice?
```gdscript
# Lesson projectile.gd
class_name Projectile3D extends Area3D
```
```gdscript
# Practice bullet.gd, no class_name, so we can call Node3D?
extends Area3D
```
Thanks!10Aug. 31, 2024
Function name Typo, when picking random_angleMelabelaHi, wanted to point out this typo:
Two places in the lesson text, where it suggests using `rand_range()` fn -- *"f" is missing before underscore* -- it should be `randf_range()` :
- "**Try this on your own**" box -> Hint 1
- "Here's how I've done it:" -> Point 110Aug. 24, 2024
Practice L7.P1 typoTJHi! Just mentioning a small typo in Hint 3 of the practice, where it mentions the wand instead of the machine gun.10Jul. 29, 2024
Understanding Transform of Child SceneTJIn the lesson we save the wand Marker3D node (with the Timer child) as a scene `wand.tscn`. We do this after positioning the wand Marker3D node in the scene `player_3d.tscn`. Upon further inspection, in the new child scene `wand.tscn`, the position of the root node is showing the same non-identity transform it had in `player_3d.tscn` before exporting. In my case it has x-coordinate 0, y-coordinate 0.502, and z-coordinate -0.66.
What I don't fully grasp is if it's necessary for a child scene to define a (non-identity) transform on its root node in order to achieve a certain positioning of it in the parent scene where it gets instantiated. I was so far under the impression that the parent scene always assigns a transform to the root node of each instantiated child scene. So I'm surprised that inside the `wand.tscn` scene the root node actually has a non-zero position.
Could you provide some guidance about what is commonly done in Godot development? Are there best practices for root-transforms in child scenes vs their instantiations in parent scenes, or will future lessons elaborate more on this topic? Or perhaps a small note in the current lesson could help.
Thanks for your help!20Jul. 26, 2024
Shoot Input differenceexpensive-wallabyEarlier when we originally set up the Input map for shoot you used space and xbox button A, now you're changing shoot to Ctrl and right trigger.10Jul. 14, 2024
Bug with degrees and radiansdkarlberg I believe, there is a bug in the included code for *wand.gd.*
```gdscript
@export_range(0.0, 90.0, 0.1, "radians_as_degrees") var max_random_angle := PI / 10.0
```
The range clearly indicates, that max_random_angle should be in degrees, therefore it would be right to set the initial value instead to following
```gdscript
@export_range(0.0, 90.0, 0.1, "radians_as_degrees") var max_random_angle := rad_to_deg(PI / 10.0)
```
Therefore, code inside *shoot()* shall be fixed as well to
```gdscript
func shoot() -> void:
# ...
var random_angle := randf_range(-max_random_angle / 2.0, max_random_angle / 2.0)
projectile.rotate_y(deg_to_rad(random_angle))
```
With call to *deg_to_rad()* to bring it back from degrees to radians, which are used by Godot.60Jul. 11, 2024
Potential typo?half-kuduIn the "Coding the shooting mechanic" section there's a sentence that says "We can assign the projectile's global transform to the wand's global transform to change both the position and rotation at once." I might be misunderstanding but should those objects be reversed, i.e. should it say "assign the wand's global transform to the projectile's global transform"?10Jul. 10, 2024
Using the alternative @tool script from L6 gives error:SniffiI used the alternative @tool script for the projectile_3d.gd during this lesson, which works great when messing around in the editor. (Not sure if i was supposed to use it as an alternative for the following lessons though, but i did just out of curiosity)
When you shoot a bullet it gives the error `Invalid set index 'scale' (on base: 'Nil') with value of type 'Vector3'`when `_visual.appear()` gets executed the first time here:
```gdscript
# projectile_3d.gd
@tool
class_name Projectile3D extends Area3D
@export var projectile_vfx: PackedScene = null: set = set_projectile_vfx
...
func set_projectile_vfx(new_projectile_scene: PackedScene) -> void:
...
_visual = projectile_vfx.instantiate()
add_child(_visual)
_visual.appear()
```
The error is at this line inside `fireball.gd` :
```gdscript
# fireball.gd
func appear() -> void:
...
_core.scale = Vector3.ZERO # _core is null
```
The variable `_core` is null and since it is null it has no property scale.
What seems to fix it is either if i replace the last line inside the setter with this:
```gdscript
# projectile_3d.gd
func set_projectile_vfx(new_projectile_scene: PackedScene) -> void:
...
_visual.tree_entered.connect(_visual.appear)
```
or change `await tree_entered` to `await ready` (which based on this lesson breaks the expectation that the setter function should run instantly though)
```gdscript
# projectile_3d.gd
...
if not is_inside_tree():
await ready
_visual = projectile_vfx.instantiate()
add_child(_visual)
_visual.tree_entered.connect(_visual.appear)
```
I´m not sure if this is the most elegant way in this case though and i´m also not 100% sure why the same 3 lines of code
```gdscript
# projectile_3d.gd
_visual = projectile_vfx.instantiate()
add_child(_visual)
_visual.appear()
```
behave differently when they get called in the setter compared to the `_ready()` function in the other script. What exactly is the difference between `await tree_entered` to `await ready` ?
As always great lesson and thanks alot!20Jul. 03, 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.