+1 vote

The title pretty much says everything, I need an instance (that spawns at the position of a sprite which follows the mouse and snaps to a tile map's tiles) to delete another instance if there is another one in the exact position. The instances aren't stored in the tilemap at all, they are stored in a Node2D ( which is separate to the Main Node2D of the scene) with a Y-Sort in it. I have asked this before but I'm trying to take a different approach to it. My current idea is for the newly instanced object to detect if another instanced object is in the exact same position, and if there is another instanced object, the newly instanced object gets the old instance's id and delete said old instance.
Possibly something like this? :

(In the Main scenes script which handles placing the buildings)

func place_building():
if BuildingValue.buildingToPlace == 0:
    var A = preload("path/A.tscn")
    var A_spawn = A.instance()
    A_spawn.position = $HighlightBox.position
    $Node2D.add_child(A_spawn)

if BuildingValue.buildingToPlace == 1:
    var B = preload("path/B.tscn")
    var B_spawn = B.instance()
    B_spawn.position = $HighlightBox.position
    $Node2D.add_child(B_spawn)

func _input(event):
    if Input.is_action_just_released("place") && GameManager.can_place == true:
        place_building()
    else:
        if ExampleNewInstance.position == ExampleOtherInstance.position:
            var ExampleVar = ExampleOtherInstance.get_instance_id()
            $Node2D.remove_child(ExampleOtherInstance)

The top function is just an example of the place_building() function.
I don't know if this even remotely close, my guess is it's not but I'm just sharing my thinking process.
Thanks in advance :D

Godot version version 3.4
in Engine by (58 points)

1 Answer

+1 vote

I don't think the objects you're placing should know how to interact with other objects you've placed (unless that's a game mechanic). It would be better to let the parent node know how to manage that. Assuming buildings are sized uniformly, I would create a dictionary where the keys are the positions where building instances are currently located and the value being either the building object itself or the object's instance id. Then placing would be something like this:

func place_building_at_position(building_position):
    var building_at_position = building_dictionary.get(building_position)

    if not building_at_position:
        pass # no building in the dictionary, nothing to clean up
    elif not is_instance_valid(building_at_position):
        return # can't be too careful when dealing with mouse stuff
    elif $Node2D.is_a_parent_of(building_at_position):
        # clean up old node if we found one
        $Node2D.remove_child(building_at_position) # or instance_from_id(building_at_position)
        building_at_position.queue_free()

    # just make place_building() return the object instanced or its id
    var new_building = place_building()
    building_dictionary[building_position] = new_building
by (3,898 points)

Sorry didn't see this till now!
After asking this question I ended up coming up with a rather convoluted solution, it works but probably isn't the best way to do it, though it is pretty reliable, I haven't had any problems so far. The solution I came up with was creating a timer inside the instances set to 0.08 seconds, and a variable inside the instances scripts called waitfortimer.
This is how I did it:

var wait_for_timer = true

func _ready():
    $Timer.start()
    wait_for_timer = true #when wait_for_timer is true, this instance can not be deleted

func _on_Area2D_area_entered(area):
    if !wait_for_timer: #if wait_for_timer is false then delete self
        queue_free() #this will delete the object if the timer isn't running

func _on_Timer_timeout():
    $Timer.stop()
    wait_for_timer = false #when timer finished set wait_for_timer to false

Just set the Timer to autostart then:

func _on_Area2D_area_entered(area):
    if $Timer.is_stopped():
        queue_free()
Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.