All Dialogue Happening at the Same Time

Godot Version

Godot 4.7.1

Question

hi, me again. i’m trying to do everyone’s most beloved thing to do in godot: Make Dialogue Work Without An AddOn. i’ve fumbled my way through getting it to pop up and and read text etc etc.

now i have an issue where regardless of who the player is talking to/in range of, all possible NPCs that can talk speak at the same time. shown here with collision shapes on, where i’m only supposed to be talking to the NPC i’m in front of:

relevant code and trees (i tried to fix things by adding self. but it did not work):

moving NPC:

var player: CharacterBody2D
var player_in_talk_zone: bool = false
var is_talking: bool = false
if Input.is_action_just_pressed("interact"):
		if not self.is_talking:
			moving = false
			self.is_talking = true
			dialogue.start()
			anim.play("idle_down")
		else:
			return
func _on_dialogue_area_2d_body_entered(body: Node2D) -> void:
	if body.has_method("player"):
		player = body
		player_in_talk_zone = true


func _on_dialogue_area_2d_body_exited(body: Node2D) -> void:
	if body.has_method("player"):
		player = body
		player_in_talk_zone = false
		self.is_talking = false

func _on_dialogue_dialogue_finished() -> void:
	await get_tree().create_timer(1.0).timeout
	self.is_talking = false
	moving = true

and on the unmoving NPC i’m talking to in the screenshot:

var player: CharacterBody2D
var player_in_talk_zone: bool = false
var is_talking: bool = false
func _physics_process(delta: float) -> void:
	if Input.is_action_just_pressed("interact"):
		if not self.is_talking:
			self.is_talking = true
			dialogue.start()

func _on_dialogue_area_2d_body_entered(body: Node2D) -> void:
	if body.has_method("player"):
		player = body
		player_in_talk_zone = true


func _on_dialogue_area_2d_body_exited(body: Node2D) -> void:
	if body.has_method("player"):
		player = body
		player_in_talk_zone = false
		self.is_talking = false

func _on_dialogue_dialogue_finished() -> void:
	await get_tree().create_timer(1.0).timeout
	self.is_talking = false

thank you for reading! next time i might just download and try to learn dialogic and hope that it’s a little easier tbh.

Seems like this script does nothing to deduce if the player is nearby before actually talking. You do have a player_in_talk_zone variable and it would be opportune to use it.


Though it’s based on if the body has a method named player which is very strange, usually one would use groups with body.is_in_group("player") or class_names with body is Player

i did switch the dialogue_area_2d_body_entered/exited to now check if the body’s in the player group (i forgot that i initially made a group), so that’s fixed. i’m having trouble with it checking the player_in_talk_zone variable though; if i put if Input.is_action_just_pressed(“interact”) and player_in_talk_zone == true: then it stops responding altogether.

how large is your dialogue collision shape? Have you tried playing with “Visible Collision Shapes” on in the debug menu, top-left?

Try adding print statements and post your edited script

the pink boxes are the dialogue collision shapes (the blue pills are the regular ones). no statements are being printed from the NPC i’m trying to interact with, only the one that i’m away from.

if Input.is_action_just_pressed("interact") and player_in_talk_zone == true:
	if not is_talking:
		print("talk zone moment")
		moving = false
		is_talking = true
		dialogue.start()
		anim.play("idle_down")

can you post their entire script?

i’ll just be posting the moving one since there’s no difference in how they get/say dialogue:

extends CharacterBody2D

@onready var anim: AnimatedSprite2D = $AnimatedSprite2D
@onready var path: Path2D = $".."
@onready var path_follow: PathFollow2D = $"../PathFollow2D"
@onready var dialogue: Control = $Dialogue


@export var move_speed: float = 30
@export var loop_path: bool = true
@export var moving: bool

var last_position: Vector2

var player: CharacterBody2D
var player_in_talk_zone: bool
var is_talking: bool = false

func _ready() -> void:
	moving = true
	position = path_follow.position
	last_position = position
	
	
func _physics_process(delta: float) -> void:
	if moving == true:
		path_follow.progress += move_speed * delta
		position = path_follow.position
	
		var movement:= position - last_position
		if movement.length() > 0.1:
			_animate(movement)
		
		last_position = position
	
	if Input.is_action_just_pressed("interact") and player_in_talk_zone == true:
		if not is_talking:
			print("talk zone moment")
			moving = false
			is_talking = true
			dialogue.start()
			anim.play("idle_down")

func _animate(movement: Vector2):
	var anim_name := "walk_"
	if moving == true:
		anim_name += ("right" if abs(movement.x) > abs(movement.y) and movement.x > 0
			else "left" if abs(movement.x) > abs(movement.y) else "down" if movement.y > 0 else "up")
		anim.play(anim_name)

func _on_dialogue_area_2d_body_entered(body: Area2D):
	if body.is_in_group("Player"):
		player_in_talk_zone = true


func _on_dialogue_area_2d_body_exited(body: Area2D):
	if body.is_in_group("Player"):
		player_in_talk_zone = false
		self.is_talking = false

func _on_dialogue_dialogue_finished() -> void:
	await get_tree().create_timer(1.0).timeout
	self.is_talking = false
	moving = true