Essentially, I procedurally generate a bunch of objects at run time and when the user clicks a location I want to delete the object at that location. The objects are named based on their coordinates. I have tried numerous ways to find the given node and while everything appears to be correct, I either get an error or a null result. The current code, which is giving a null result is:
var node_to_get = "BlockBox" + str(int(item_place_instance.position.x) ) + "x" + str(int(item_place_instance.position.z))
print(node_to_get)
var delete_box = get_tree().get_root().find_child(node_to_get)
print (delete_box)
delete_box always shows as null. No error is generated.
Looking at the live object list of the active game I clearly see the node in the list and the debug data shows the node_to_get variable reflecting the correct name yet when I feed this node name into the find_child the result is always null.
find_child() is a very inefficient way of handling this.
I would suggest to completely disregarding this solution and go into the way of storing your BlockBoxes in a Dictionary. Then you can do something like that:
var boxes: Dictionary[Vector2, Node]
func instantiate_blockbox(coordinates: Vector2) -> void:
var blockbox = BLOCKBOX.instantiate()
blockbox.position = coordinates
boxes[coordinates] = blockbox
func delete_blockbox(coordinates: Vector2) -> void:
if boxes.has(coordinates):
boxes[coordinates].queue_free()
Yeah, literally 5 minutes after I entered this question, and many hours of trying to get it to work, researching, etc. I found a reference to the ,true,false on find_child. Until then I missed that find_child had parameters.
Since I am creating the blockbox objects (which are CSGBoxes with collision active to force navigation around them) dynamically during run time I found they don’t really have an owner (like editor objects have) even though I was assigning them as a child of another node.
It wouldn’t work even if they had an owner. The problem is that you call it on root which never has an owner. If you look at the source code of get_child(), you can see that recursion is broken when a node without an owner is encountered so the branch underneath it is not searched. Since root is at the root, the recursion is broken immediately at start and no nodes get checked at all.
If nodes you’re trying to get have an owner, doing get_tree().current_scene.get_child(node_to_get) will work as well, as the tree traversal in that case doesn’t start from the owner-less root.
These are being created as obstructions in a navigation mesh. Think of most “Sim” or “Tycoon” style games where you create paths that NPCs walk around on. I’m trying to achieve this.
I went down the route, initially of making each path a navmesh but I couldn’t get them to connect together. Instead I make the entire field one big navmesh and then block off everywhere that isn’t a path with the blockbox. When you add paths I remove the blockbox at that location and add a path object. Now the NPCs see that as a valid area to walk on.
In the overall game creating/destroying paths is a relative small part of the game play. Also the playing field is not that large so even calling bake after each path change to update the nav mesh has no visible impact to performance.
If there is some other way to achieve this I’m definitely open to it, but so far I’ve yet to find any example that shows navmesh usage as an additive process (add additional areas). All examples I found are subtractive… make it all naviagable then toss out objects to obstruct the agents.
I wasn’t looking at it that way. Just starting at root to ensure that if the branch with these objects gets moved as part of future project organization that I don’t break the script and node path.
At first I wasn’t sure how this would work as I don’t necessarily know where the node will be in the future, but if I understand this correctly, the node itself is being reference in the dictionary (along with coordinates to be able to find it in the dictionary) so there would be no need to find the path as the node itself is already known. This would allow the queue.free to work regardless of where it is.
I just implemented in literally a couple of minutes. I kept the same string logic I was using to name the nodes and used that in places of the Vector2 (technically a vector3 in my game but i only use X and Z). Worked perfectly.
Defined in global script to be accessible across various nodes/scripts:
var blocking_locations: Dictionary[String, Node]
Created with: (note path_objects will eventually be an array of scenes for each path type, the “1” will be replaced with a variable for which one is active for placement)
var node_to_get = str(int(item_place_instance.position.x))+"x"+str(int(item_place_instance.position.z))
if global.blocking_locations.has(node_to_get):
global.blocking_locations[node_to_get].queue_free()
I don’t get this, and I see it a lot on this forum.
An OP gets a solution to their problem, then they implement a trivially modified version of it and mark their post as the solution. How is your post a solution when the actual hard part of the solution was served to you on a platter by someone else?
This is extremely bad form. It’s disrespectful towards people who invest their free time to solve your problem for you. The least you can do is be courteous and mark their answer as the solution.
@normalized, actually it was me who marked this response as a solution (I can do that as a mod), so there’s no need to get your anger out on @hungrycatgames
When I see a post that’s been clearly solved, I would mark it as solved with the post that had the best answer. In this case - I don’t want to just take the credit for myself, I’d rather mark his answer as a solution, I don’t mind. I already got my fair share of fake internet point
But in general - I agree with your statements and encourage people to mark the helper’s post as a solution, even when you implemented some slight adjustments to the solution.
You should have marked your solution then
But as you noted as well, It’s not really about this particular case. I’ve just seen this happen way too often in my short time being active here.
It’s not your fault. Your post just got caught in crossfire. I didn’t know @wchc marked your post as the solution, so I wrongly picked you as an example of a certain behavior.