Can't interact with object more than once

Godot Version

4

Question

I’m using the Dialogue Manager plugin by Nathan Hoad to recreate how you interact with objects in games like undertale, where you walk up to something, press z, and dialogue pops up. And if you press z again then it’ll go to the next line and pressing z when its at the last line will close the dialogue. But I’m running into an issue where if interact with an object you can’t do it again without leaving and going back in the Area2D. This is my code for every object (each object loads a different dialogue file):

extends Area2D
var interactable = false

func _process(delta):
* interact()

func interact():
* if interactable == true:
* * if Input.is_action_pressed(“Interact”):
* * * DialogueManager.show_dialogue_balloon(load(“res://dialogue/THEROCK.dialogue”), “start”)
* * * interactable = false

func _on_body_entered(body):
* interactable = true

func _on_body_exited(body):
* interactable = false

That happens because you set interactable false after you call show_dialogue_balloon().

By the way, you can format your code section in your post by selecting it and pressing the </> button or adding ``` before and after.

Yes but since the same button is used for everything, if I don’t set interactable to false at the end then every time you press z to advance to the next line it would open the dialogue box again trapping you there with more and more dialogue boxes popping up when you try to leave. Oh and thank you for the formatting thing

I would recommend changing the way your interaction system is designed. It would make more sense to process the input in your player script. When “interact” is pressed, you should check if there is an interactable object nearby and if the object has a method called “interact”, you call it. You can check if there is an interactable object nearby by using Area2D nodes or RayCast2D nodes.

For example, you could have an Area2D node called InteractionRange as a child of the Player. When interactable object enters the InteractionRange, you can store it in a variable. Then when the player presses “interact”, you call the interact method of that object. If there are multiple interactable objects near the player, you might need a way to check which one of them is the closest.

I reccomend using rigidbodies and a raycast connected to your playerbody, rather than areabodies! It works flawlessly for me.

Set collisions for one on physics object’s (such as the player) layers, one and ‘number X’ for rigidbodie’s/areabodie’s mask (and just one for layers) and soley ‘number X’ for player raycast’s mask.

extends RayCast2D

func _physics_process(_delta):
	if Input.is_action_just_pressed("confirmin") and self.is_colliding():
		var Scollide = self.get_collider()
		Scollide._interact()
extends Node

signal _textWriter

func _interact():
	var possum = []
	# Yip!
	possum.append("{test}")
	possum.append("[ul bullet=*]Hello my baby.
Hello my honey.
Hello my ragtime gal.")
	possum.append("{tset}")
	possum.append("New arrival, no known motive or history.")
	possum.append("But... thisth was clearly a premediated crime,")
	possum.append("Done by a proffessional crimer.")
	# Yip!
	_textWriter.emit(possum)

And…

$PupRayCast.set_target_position(Vector2(X, X))
#for different directions, each! (will be different numbers (+ / -), espically if rectangular footbox.

Using a raycast also means that you only interact with the first thing it touches! Which gets rid of the problem of touching multiple things…
Hope this banging helps mate!!

You can re-enable interactable when dialogue ends, assuming the balloon will triggers that signal

func interact():
  if interactable == true:
    if Input.is_action_pressed(“Interact”):
      DialogueManager.show_dialogue_balloon(load(“res://dialogue/THEROCK.dialogue”), “start”)
      interactable = false
      await DialogueManager.dialogue_ended
      interactable = true

it stops you from opening new dialogue boxes when you try to go to the next line which is getting closer to the solution but you still cant walk away if you do that. Trying to press z on the last line to close the dialogue will just open it again.

I’m not sure for the first issue. Sounds like dialogue_ended triggers after each line of dialogue?

Opening immediately after closing sounds like you could add a short delay in addition to on dialogue_ended

func interact():
  if interactable == true:
    if Input.is_action_pressed(“Interact”):
      DialogueManager.show_dialogue_balloon(load(“res://dialogue/THEROCK.dialogue”), “start”)
      interactable = false
      await DialogueManager.dialogue_ended
      await get_tree().creat_timer(0.5).timeout
      interactable = true