Topic was automatically imported from the old Question2Answer platform.
Asked By
Lazulily
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
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
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 wait_for_timer.
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
Lazulily | 2021-12-01 22:40
Just set the Timer to autostart then:
func _on_Area2D_area_entered(area):
if $Timer.is_stopped():
queue_free()