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