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.
Why do we need to use shooting_point in the dummy's look_at function?almirpaskIt's still not clear to me why we're using `projectile.look_at(shooting_point.global_position + shooting_point.global_basis.z)` instead of `projectile.look_at(player.global_position)`. The result of both seems pretty similar to me.10Oct. 31, 2024
L3.P1 Question & Bind() CallMoKTHey Nathan, I'm having some trouble understanding the bind() call, and this part of the lesson:
*The `timeout` signal receives no arguments, so instead, we [bind](https://school.gdquest.com/glossary/function_bound) the state we want to switch to when connecting the signal. As in the `_physics_process()` function, we use the `match` keyword to isolate code for different states.*
In the practice, i just removed the bind call and had it like this:
```gdscript
func set_current_state(new_state: States) -> void:
#...
States.SHOOT:
#...
set_current_state.bind(States.WAIT)
```
This passed me on everything except the *The SHOOT state transitions to the wait state.*
So I realized that the bind function was needed for connecting the timer timeout, so I created an arbitrary 0 second timer, and passed the practice.
```gdscript
func set_current_state(new_state: States) -> void:
#...
States.SHOOT:
#...
get_tree().create_timer(0).timeout.connect(
set_current_state.bind(States.WAIT)
)
```
But I looked at your solution, and you called the set_current_state without the bind
```gdscript
func set_current_state(new_state: States) -> void:
#...
States.SHOOT:
#...
set_current_state(States.WAIT) #
```
Are you able to help me understand why we're able to call a function inside of itself and a little more/simplified explanation of the bind() call?
Let me know if my question is too big/vague.
Thanks Nathan!40Oct. 17, 2024
Is there a better way of doing this?tender-dragonflyI did what I thought was the best of doing the last challenge but... I have a feeling there is a better way of doing it rather than completely relying on signals
```gdscript
extends CharacterBody3D
enum States {
LOOK_AT_PLAYER,
WAIT,
FIRE_PROJECTILE,
EXPLODE,
}
var player: CharacterBody3D = null
@export var projectile_scene : PackedScene = null
@onready var shooting_point: Marker3D = %ShootingPoint
@onready var explosion_area: Area3D = $Explosion_Area
const EXPLOSION = preload("res://assets/vfx/explosion/explosion.tscn")
@onready var explosion_effect = EXPLOSION.instantiate()
@onready var anim_player: AnimationPlayer = $AnimationPlayer
func _ready() -> void:
player = get_tree().root.get_node("Level/Player3D")
set_current_state(States.LOOK_AT_PLAYER)
var current_state : States = States.LOOK_AT_PLAYER:
set = set_current_state
func set_current_state(new_state: States) -> void:
current_state = new_state
match current_state:
States.LOOK_AT_PLAYER: #This matches states and then gives you the code within the state.
get_tree().create_timer(2.0).timeout.connect(
set_current_state.bind(States.WAIT)
)
States.WAIT:
get_tree().create_timer(0.1).timeout.connect(
set_current_state.bind(States.FIRE_PROJECTILE))
States.FIRE_PROJECTILE:
var projectile: Projectile3D = projectile_scene.instantiate()
add_sibling(projectile)
projectile.global_position = shooting_point.global_position
projectile.look_at(
shooting_point.global_position + shooting_point.global_basis.z
)
get_tree().create_timer(0.5).timeout.connect(
set_current_state.bind(States.LOOK_AT_PLAYER)
)
States.EXPLODE:
return
func _physics_process(delta: float) -> void:
match current_state:
States.LOOK_AT_PLAYER: #This matches states and then gives you the code within the state.
var direction := global_position.direction_to(
player.global_position)
var target_rotation_y := Vector3.FORWARD.signed_angle_to(
direction, Vector3.UP) + PI
rotation.y = lerp_angle(
rotation.y, target_rotation_y, 10.0 * delta)
func explode(body: Node3D) -> void:
set_current_state(States.EXPLODE)
anim_player.play("blinking")
func _on_animation_player_animation_finished(anim_name: StringName) -> void:
add_sibling(explosion_effect)
explosion_effect.position = global_position
queue_free() # Replace with function body.
```
10Sep. 21, 2024
Not passing practice testsvast-baboonHowdy! I'm wondering what I'm doing wrong with the practice scene. When I run the tests, I get:
> The WAIT state transitions to the SHOOT state. - ✓
> The WAIT state lasts 0.7 seconds. - ✓
> The SHOOT state transitions to the WAIT state. - ✓
> The turret shoots a bullet moving forward from the spawning point. - x
> The SHOOT state spawns a bullet. - x
My WAIT and SHOOT states are below.
```gdscript
match current_state:
States.WAIT:
get_tree().create_timer(0.7).timeout.connect(
set_current_state.bind(States.SHOOT)
)
States.SHOOT:
var bullet = bullet_scene.instantiate()
owner.add_sibling(bullet)
bullet.global_position = bullet_spawning_point.global_position
bullet.look_at(bullet_spawning_point.global_position + bullet_spawning_point.global_basis.z)
set_current_state(States.WAIT)
```
When I run the test, the game viewport for my solution looks identical to the reference. Bullets shoot in the correct direction every 0.7 seconds20Sep. 18, 2024
Small typoDédéHi! First of all, great lesson.
I have noticed a small repetitive typo in the text which doesn't change anything in the value of the lesson but I thought it would be nice to point it out. You are referring to *set_state()* multiple times in the text while the code examples are using *set_current_state()*.
10Sep. 15, 2024
Using animation player for dummy explosiondeserted-walrusI'm trying the exercise at the end and the animation players "on finished" signal doesn't seem to fire. You list it in the hints as one of the viable options for doing the exercise, so I'm not sure what I'm doing wrong. I connected the signal in the mob_dummy script, but when the animation finishes, my print statement doesn't show up.
`func _on_dummy_skin_animation_finished(animation_name: String) -> void:`
`print(animation_name)`
`if animation_name == "explode":`
`var visual = explosion_vfx.instantiate()`
`add_sibling(visual)`
[https://drive.google.com/file/d/1ZdEhOlIMsL4ijxdyft4Ic-BPtI4Na36P/view?usp=sharing](https://drive.google.com/file/d/1ZdEhOlIMsL4ijxdyft4Ic-BPtI4Na36P/view?usp=sharing)30Sep. 08, 2024
Unique name vs Dragging into the editordeserted-walrusGoing through this course I see you always suggest setting nodes to "access as unique name" so that we can access them in our script. Before this course I always did the ctrl+drag into the editor, which gives you a $ instead of a % but seems to work. What's the actual difference?10Sep. 08, 2024
Are state machines good for this situationliuti_devHi! First of all: great lesson! My favorite so far.
I would like to know if state machines are suitable for situations of handling multiple "similar" states like a sequence of attacks in a combo. Or even different possibilities like attacking while jumping, etc. If not, is there a different pattern you would recommend me? 10Sep. 04, 2024
Question regarding state machinestained-wolverineHi :)
Would a state machine make sense in case you wanna walk and shoot at the same time? Is there another pattern for this case?
10Aug. 24, 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.