Area3D's, Signals and Copies - having issues - GDScript

Godot Version

4.3 Stable

Question

Hi all. I am having an issue with an area3D signal. I have an object that if the player walks into the collision of an Area3D, that an animation has a chance to play along with some audio. This function is working just fine. However, if I copy that object in the scene, all of the copies will start the animation. I have tried everywhere I can think of to set the objects as unique, but it just doesn’t seem to be working. The code is below. (I have the random range set to 7,7 just so I can test it every time.)

Code on the player for the signal:

func _on_torch_body_entered(body: Node3D) -> void: if body is CharacterBody3D: var doispeak = RandomNumberGenerator.new() var SCnum = doispeak.randi_range(7,7) if SCnum == 7 && isTorchTalking == false: var whattoplay = RandomNumberGenerator.new() var SFnum = whattoplay.randi_range(1,3) if SFnum == 1: audio_file = load("res://Sounds/Sound Effects/Creatures/Torches/torch_sound_1.wav") enemy_audio.stream = audio_file enemy_audio.play() elif SFnum == 2: audio_file = load("res://Sounds/Sound Effects/Creatures/Torches/torch_sound_2.wav") enemy_audio.stream = audio_file enemy_audio.play() elif SFnum == 3: audio_file = load("res://Sounds/Sound Effects/Creatures/Torches/torch_sound_3.wav") enemy_audio.stream = audio_file enemy_audio.play()
Code on player to set torch is talking

func _physics_process(delta): isTorchTalking = enemy_audio.playing

Code on torch:

func _process(_delta: float) -> void: if player.isTorchTalking == true: animated_sprite_3d.play("speak") elif player.isTorchTalking == false: animated_sprite_3d.play("idle")
Any guidance would be appreciated.

I assume the objects you’re copying are the toches, and the player has an Area3D, correct?

All your torch objects check for the same value on player: player.isTorchTalking. Because there’s only one player and all torches access the same value, they do the same thing.

To have them behave independently, you’ll have to separate their logic from the player, so each of them can hold their own state/variable. It’s better to have the torch logic on the torches and not the player anyways. Imagine you add more enemies and features, it would get quite messy, no? :grinning_face_with_smiling_eyes:

Let’s start by moving the isTorchTalking variable to the torch script. If you want multiple enemies to make sounds at once, why not move the audio player to each torch as well? And it would probably be easier to give each torch an Area3D on their own and detect the player approaching instead, but you can make it work in many ways.

If you do that, you can almost cut-and-paste the torch logic from the player into the torch, and they should now act independently.

Also, just a few additional notes:

  • You’re loading the sounds every time a sound has to play. It would be better to load them at _ready once, and store the sounds in variables, or even better, use preload.
  • You’re calling animated_sprite_3d.play() every frame in the torches. That’s not needed: play() triggers the animation, and the animation player will continue playing the same animation until the end (or forever if it’s looping), or until you call a different function on it. You should call play() only once, when the value of isTorchTalking changes, and you’ll quickly find you don’t actually need _process for this at all.
  • You’re setting the value of isTorchTalking in_physics_process, while it only really changes when the enemy audio begins and stops playing. If you change the code to set this value when this happens and stop using _physics_process for it, your code will be cleaner and will probably help solve you the previous bullet point. ^^ You can use the finished signal of the AudioStreamPlayer for this.

Hope this helps! ^^

1 Like

Please format your code using ``` on the line above and below your code to make it easier for us to read. @Xenareee made a bunch of really good suggestions.