Godot Version
4.6
Question
Hello!!! So im trying to make it so that you can only interact with something if you enter the area it is in. THis isnt really an extension problem, i know im working with the dialogue manager here but i know the problems my code :3
So, i tried a lot of things, i tried making the unhandled_input into a conditional statement, then the area3d. I tried a few other things too but nothings worked so far, so what am i doing wrong?
heres the code:
extends StaticBody3D #a charecter i wanna interact with
var dialogue_resource = load ("res://DFD.dialogue")
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("interact"):
DialogueManager.show_dialogue_balloon(dialogue_resource, "start1")
Make an Area3D that is a child of this body. Then use Area3D::overlaps_body() to test if the player is inside that area. If it is - show the dialogue.
Okay, so i got this:
var player = %DialogueInteraction
var dialogue_resource = load ("res://DFD.dialogue")
func _unhandled_input(event: InputEvent) -> void:
if Area3D.overlaps_body("player"):
if event.is_action_pressed("interact"):
DialogueManager.show_dialogue_balloon(dialogue_resource, "start1")
but it gave me the error âError at (10, 29): Invalid argument for âoverlaps_body()â function: argument 1 should be âNodeâ but is âStringâ.â
The argument to overlaps_body() needs to be a reference to playerâs character body node.
1 Like
okay, i did that, and then it said i needed to make this an instance. I definitely made some stupid mistakes after that. I thought instance meant a scene, and since it worked that way before, i converted the area i wanted to interact with the other area3d in a new scene and parented it to the player. I then did this:
extends StaticBody3D
@onready var player = "res://Scenes/area_3d.tscn" #area parented to player to interact, didnt bother to rename
@onready var dialogue_resource = load ("res://DFD.dialogue")
@onready var actionable = "res://Scenes/actionable.tscn" #the area3d parented to other characters to talk
func _unhandled_input(event: InputEvent) -> void:
if player.overlaps_body(actionable):
if event.is_action_pressed("interact"):
DialogueManager.show_dialogue_balloon(dialogue_resource, "start1")
and it gave me the error E 0:00:03:177 _unhandled_input: Invalid call. Nonexistent function âoverlaps_bodyâ in base âStringâ.
Try using the collision detection of the area to get the player, instead of always having a reference to the player, which is somewhat difficult to get; for example your @onready var player and actionable are not references to nodes, instead they are string paths to files, which arenât useful in this context.
This is a very common pattern of detecting all body overlaps, and filtering out the ones you want
extends StaticBody3D
var player: Player = null # we do not know who the player is yet
func _on_body_entered(body: Node3D) -> void:
if body is Player:
player = body # we found the player
func _on_body_exited(body: Node3D) -> void:
if body == player:
player = null # player left the area, forget about them
func _unhandled_input(event: InputEvent) -> void:
if player != null: # only if we know of the player
if event.is_action_pressed("interact"):
DialogueManager.show_dialogue_balloon(dialogue_resource, "start1")
1 Like
okay so now i have this:
extends StaticBody3D
var player: Player = null
var dialogue_resource = load ("res://DFD.dialogue")
func _on_actionable_body_entered(body: Node3D) -> void:
if body is Player:
player = body
print("body entered")
func _on_actionable_body_exited(body: Node3D) -> void:
if body == player:
player = null
but its not detecting the area is entered, it wont print what i told it to print.
You could tweak the print to let us know if it detects anything and what that anything might be
func _on_actionable_body_entered(body: Node3D) -> void:
print("Something entered: ", body)
if body is Player:
player = body
print("player entered; yay!")
It could be that the signal is incorrectly connected, or that your player you are trying to detect is not of class_name Player
oh, i was being a little dumb haha. it was on the wrong collision layer :,D
1 Like
Not the point of this thread, but is there any way i can disable and enable some controls when i press e? (e is interact)
Itâs best to use some sort of variable as a condition for if statements, similar to how the sample uses player != null to allow interactions. If there is more state to consider such as dialogue currently running then you can use a variable that keeps track of that. Seems like dialouge manager 3 doesnât have a built in variable for that, but you can track it via signals DialogueManager.dialogue_started and DialogueManager.dialogue_ended
Thank you so much <333333
Im just going to put this here in case anyone is looking for it later:
to stop your player from moving during the dialogue, you put this code into your player script:
func _physics_process(delta: float) -> void:
if DialogueManager.dialogue_started:
set_process(false)
if DialogueManager.dialogue_ended:
set_process(true)
move_and_slide()
1 Like
wait a second, its still not working again. its still moving my charecter when dialogue is running (the first test i was stuck in a collision shape i guess)
Signals do not work on if statements, when used as part of an if the signal will always and immediately evaluate to true, so itâs not useful like this.
You must connect functions to the signals, you could do this on _ready for your player
func _ready() -> void:
DialogueManager.dialogue_started.connect(_on_dialogue_started)
DialogueManager.dialogue_ended.connect(_on_dialogue_ended)
func _on_dialogue_started() -> void:
set_process(false)
func _on_dialogue_ended() -> void:
set_process(true)
okay, and i feel like this is a stupid quiestion, but where do i actually connect the dialogue? i dont want to have to do this for every line of dialogue i type :,D but when i copied the code it still didnt freeze the player, i feel as though im simply just missing something im sorry
set_process only stops the _process function, if overriden, from running. If your player moves only inside the _process override, then they would freeze. This isnât common in CharacterBody-type players as they would use _physics_process and may have other forces and functions for movement.
This code should go on your player script, but Iâm betting set_process just isnât the right function for your use case. Rather it may be better to have a new variable for âin_dialogueâ that you can add to other movement and interaction if statements.
im sorry i dont think i understand :,D
First you have to know how your player moves. Using set_process(false) probably will not stop movement, you would have to share your playerâs script for us to know for sure.
The most common or consistent way to prevent movement would be to use a variable tracking if the player should be âfrozenâ, then changing the input to zero if set.
var frozen: bool = false
func _physics_process(delta: float) -> void:
var direction := Input.get_vector("left", "right", "up", "down")
if frozen:
direction = Vector2.ZERO
Okay thank you 
Not sure if this is a godot problem or a dialogue manager problem haha, please correct me, but when I made another dialogue file and attached it (before i attached you code so it couldnt be that), it started saying âInvalid call. Nonexistent function âget_next_dialogue_lineâ in base âNilâ.â
Both have this code (Changing the âload resourceâ and âstart1â so that they load seperate dialogue scripts):
extends StaticBody3D
var player: Player = null
var dialogue_resource = load ("res://DFD.dialogue")
var frozen: bool = false
func _physics_process(delta: float) -> void:
var direction := Input.get_vector("Left", "Right", "Up", "Down")
if frozen:
direction = Vector2.ZERO
func _on_actionable_body_entered(body: Node3D) -> void:
print("something entered")
if body is Player:
player = body
print("body entered")
func _on_actionable_body_exited(body: Node3D) -> void:
if body == player:
player = null
func _unhandled_input(event: InputEvent) -> void:
if player != null: # only if we know of the player
if event.is_action_pressed("interact"):
DialogueManager.show_dialogue_balloon(dialogue_resource, "start1")
frozen = true
Would this be just an easy fix? I keep havign these kinds of problems lol
considering you do not call get_next_dialogue_line in this script I think it must be a part of the dialogue manager, I am not sure what the solution would be.