trizZzle exactly as you described, but this is kinda stupid, that you cant set the position of instanced object before adding it to the parent. If i add it to the root then it will still spawn somewhere in the world and then after the next frame it will be moved to the correct position. What if there is another player moving about the same coordinates, then that player will collide with the object, every time someone adds it to the world.
Child position is not setting before adding it to parent
- Edited
I just asked my friend (chatgtp):
If you want to ensure that the position change is applied immediately, you can call instance.update_transform() after setting the position:
func newthing():
var instance = something.instantiate()
get_tree().root.add_child(instance)
instance.position = Vector3.ZERO
instance.update_transform() # Force an immediate update of the node's transform
This will force an immediate update of the node's transformation, ensuring that the change in position is applied before the next frame is rendered. Keep in mind that forcing an immediate update can have performance implications, so use it judiciously depending on your specific use case.
EDIT: I didn't know that positions where updated in the next physics process frame. Good to know.
It's force_update_transform()
- Edited
kuligs2 but unfortunately its still not working
I didn't expect it to. I just wrote the correct function name.
Your code looks too complicated. There may be bugs, including ones in parts of code you didn't show.
If you already have the preview block on the position why just not use it? Or place the block from mousedown event handler.
Anyway, it'd be best to make a minimal reproduction project and post it for inspection
xyz The code is complicated because its code, not a hello world example oneliner. Why do you say im not using the block? Im placing it at the mouse coordinates in the world. The problem is that when i set the position in the world and add it to parent (add_child) the position is not the one that i set/mouse pointer. Its the parent node position, which in my case is a node inside a player instnace.
Here is the project as is. Run it, press start, then use middle mouse button to activate the building mode then use right mouse button to place the block.
https://share.apefront.lv/s/4NiGqN6WPEARFzm
- Edited
- Best Answerset by kuligs2
kuligs2 The code is complicated because its code
No, your posted code snippet looks too messy and complicated for what it's supposed to do. Because of that it's easy to lose track of what's happening, which precisely is the case here. You forgot to actually update the position of newly added block:
Instead of just:
$PreviewBlock.add_child(newWall)
Do:
$PreviewBlock.add_child(newWall)
snap_block(result, newWall)
In general, the whole thing should be rewritten to avoid ugly nested if/elses and duplication of parts of code. For example, this needlessly appears twice in a relatively short function:
var rid_wall = get_rid_from_node(newWall)
var result = get_ray_results(rid_wall)
Doing things like this is an open invitation to bugs.
xyz i appreciate you giving me your attention and time for helping. The code is what it is, its not a game, its not an art piece, its my way to learn how to do things.
When it comes to sequence of events, i would understand that before i show an object in the world, i would set its location, then add object to the world, this makes sense,
But apparently godot is ass backwards where you have to add object to world then set its position.
Either way it works, changing the
snap_block(result,newWall)
$PreviewBlock.add_child(newWall)
to
$PreviewBlock.add_child(newWall)
snap_block(result,newWall)
also fyi, if i add the block to world node not player node then the first code works too. So idk..
And please explain what you meant with:
For example, this needlessly appears twice in a relatively short function:
var rid_wall = get_rid_from_node(newWall) var result = get_ray_results(rid_wall)
These are different functions that return different values.
Given that godot is ass backwards and wont show me values when i put line breaks and try to debug what kind of value i get from methods/properties, i have to define vars pretty much each line to see what kind of value it is.
thanks~!
- Edited
kuligs2 You just don't have full understanding of how realtime graphics (including this engine) works. So exercising some restraint before passing the final judgement may be in order
The code tidiness is not for winning awards, it primarily serves you, the developer, so you don't end up tangled in unwieldy mess (and puzzling bugs such as this one )
The order of setting the position vs parenting the node is irrelevant as long as the proper position is set before the current frame finishes processing. You didn't do so but instead you updated the position as late as the next frame so you got one frame drawn with non-updated position.
As for what I meant about code duplication; your function has two separate blocks of code that do exactly the same thing. It's a sign that control flow can and should be improved.
I'd write this whole function as follows, eliminating most of repetition and making it almost twice as short:
func new_block_logic():
if not is_preview_block:
remove_preview_block()
return
var blocks = $PreviewBlock.get_children()
var wall = wall_block.instantiate() if blocks.is_empty() else blocks[0]
if blocks.is_empty():
wall.top_level = true
$PreviewBlock.add_child(wall)
var raycast_result = get_ray_results(get_rid_from_node(wall))
if raycast_result: snap_block(raycast_result, wall)
else: remove_preview_block()
The whole thing could architecturally be made even simpler if you don't instantiate the cursor block all the time but instead just keep it alive and hide/show it as needed.