Override set_position() and Get Callbacks in Godot 3

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Hammer Bro.

In Godot 2 we had to call methods for basically everything, set_pos() to move Node2Ds and the like.

In Godot 3 it’s encouraged that we set member variables directly: node2d.position = [value].

I’ve got a reasonably complex codebase and somewhere in it an object’s position is being set to a very weird value for less than a full frame – if I print the position in _physics_process(), it will never catch the blip. This makes it very difficult to debug.

In Godot 2 I could’ve added a custom script for the object and overridden set_pos() so I could put a breakpoint. But it Godot 3 updating member variables such as position does not trigger their setget methods, and I can’t add setget to position because I’m not allowed to override parent class member variables.

How can I make a function which is called every time a Node2D’s position variable changes?

I was hoping that Node2D’s set_position() would be called if it’s overridden, much like how CanvasItems’ _draw() can be overridden and will automatically and appropriately be called.

I don’t have an answer for your question, but I do have a method which may help you to better debug variables in the future.

If you don’t know about this, you can view properties while a scene is running. In the “Scene” tab, there appears something called “Remote”. When that’s clicked, it shows the running scene’s current tree. From there, you can click on any node to see its properties in the Inspector.

Hope this helps.

Ertain | 2020-06-08 04:39

That’s definitely a useful feature, but I find that when stepping through code it automatically jumps to the Node that the current line of code belongs to.

Given I don’t know where in my codebase the problem occurs (other than that it’s not happening in the node-in-question’s script), it becomes a preposterous amount of clicking just to keep an eye on the same object’s variables over time.

If you (or anyone) knows a way to keep the object on the Remote scene tab fixed while stepping through code, that’d be greatly beneficial.

Hammer Bro. | 2020-06-08 15:48

I find that when stepping through code it automatically jumps to the Node that the current line of code belongs to

Just to make sure: You’re stating that the selected node in the remote scene tree changes? That shouldn’t be the case! Anyhow, you can pause the running game by pressing F7 (or clicking the pause icon in the upper right corner of the editor). Or set breakpoints to halt the game automatically when certain lines of code are executed: Just click left of the line number for the line you want to halt on in the editor. A red dot will indicate the breakpoint, clicking it will remove the breakpoint again.

njamster | 2020-06-10 17:51

I might be on a slightly dated build (though I thought it was based on 3.2 Stable) but yes, the selected node in the remote scene changes as I step through code.

Because I don’t actually know where in my large code base the phenomenon is occurring, break points are of limited help. Especially when coupled with the fact that I can’t easily monitor the in-production values because the selected remote node keeps changing. Pausing while the game is running is also not an option in this case, since the event happens during the course of a single frame. Possibly less than a frame.

I’ll try a more recent build to see if there have been changes to the remote inspector’s behavior as that would be one means to an end, though I still feel like we’ve lost some functionality in how we’ve changed the preferred member variable access method from functions (having to call set_pos() means you know if you overrode it then your method would always be called) to direct access (can’t add a setget to variables you didn’t define).

Hammer Bro. | 2020-06-10 19:56

yes, the selected node in the remote scene changes as I step through code.

By “step through code” you mean using breakpoints? It will select the node to which the script containing the breakpoint is attached to. As far as I know, there’s no way to disable or change that behavior. I really don’t see how that would be an issue though. If you are interested in specific variables, simply print their values directly before the breakpoint.

still feel like we’ve lost some functionality in how we’ve changed the preferred member variable access method from functions […] to direct access

Well, you are still free to use a setter-function if you want to:

func set_position(new_value : Vector2()) -> void:
    # your custom logic goes here
    position = new_value

func _process(delta : float) -> void;:
    set_position(position + Vector2(10, 10))

Edit: Also note that the way to access properties will likely change in Godot 4.0. So if you still feel the current way of doing things is limited, now would be a good time to join the discussion and make a proposal to fix what’s bothering you.

njamster | 2020-06-12 14:44

:bust_in_silhouette: Reply From: njamster

You cannot override any function unless it’s marked as virtual in the docs.

I’ve overridden non-virtual Node method add_child and it gets called as expected. I don’t think a method’s “virtual” status has any bearing on whether or not it can be overridden.

Hammer Bro. | 2020-06-10 19:49

Mhm, yeah, you seem to be correct. I read that first over here, but I guess it’s not true then and the virtual-keyword merely indicates that you’re expected to override that function. However, it’s absence doesn’t mean you cannot override it still.

njamster | 2020-06-12 14:19