-
-
Notifications
You must be signed in to change notification settings - Fork 21.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add freeing
signal to Object
#101396
base: master
Are you sure you want to change the base?
Add freeing
signal to Object
#101396
Conversation
This does not implement what the proposal asked for at least from the title, it asks for a signal when |
I would normally not be pedantic about this, but there's a stark difference between Even then, having Object itself emit this signal is possibly not a good idea. Everything in the engine would emit this signal, yet nothing would be connected to it almost all the time, and that affects both internal code and scripting. Emitting signals has a pretty small cost, but it does add up for frequent operations. |
Note that there is a notification NOTIFICATION_PREDELETE, which is sent to an Object that is to be deleted/freed. This is also how GDScript operates a destructor. |
This PR is currently too extreme in many ways, but I have a few thoughts as for why I'd like it. First I'd like to clarify the difference between this PR and the proposal. Yes, the proposal's title asks for nodes attached to _target = _get_nearest_enemy()
if _target:
_target.freeing.connect(func(): _target = null) I also described my intended use case in a comment on the PR, which requires the signal to live on Object. Ultimately I think the proposal had left a bit of technical ambiguity over where exactly the freeing signal should live, and I implemented it in a way that was preferential to how I needed it -- my apologies if this was improper. Regardless, I do think this PR does address the proposal very directly: a "queue_freeing" signal is not the same as a "freeing" signal, especially since the former doesn't even guarantee the Node is being freed (as cancel_free exists, and because queue_free defers the Node free to later). As for my use case, I have been developing several multiplayer APIs for Godot over the past 3 years. The last one I made provided integrated replication/synchronization for Nodes on a low level. To do this, the server tracks each node within its multiplayer subtree with a unique networking ID, and replicates scenes over to the client with all of its networking IDs, so that both the client and server have equivalent networking IDs for each node. These IDs are used for routing RPCs, synchronization, and replication packets without using NodePaths. These IDs are stored in separate ID repositories (note: big dictionary) on the separate client and server subtrees. I've been thoroughly developing and testing this networking model for my own projects over the last 4 months, and it has been very successful and stable for me. However, the repository is too Node-centric, and I'd like to be able to replicate/synchronize the properties within Resources too. I cannot give Resources network IDs for RPCs, synchronization, and replication, because the network repository only accepts Nodes. I could swap it to Object, but then the repository has no way of knowing when to clean up its stored IDs, besides periodically checking For most cases, yes, there are workarounds for this. The most functional workaround listed on the PR entails listening for Node tree_exiting and determining if it was queued for deletion, which is particularly obscure and only works for Nodes. But for the case of "distributed object registration in a large multiplayer API", the best (incomplete) workaround is NOTIFICATION_PREDELETE on a custom Resource base class. This might work, but the typechecking conflation adds overhead to a common registration process for an API which would otherwise be working properly for all Objects. And this could just be me personally, but I've kept finding it strange that there's no way to check for the moment any Node cleans up in Godot without implementing an unusual barrier call on Right now, the worst part about this PR is the performance overhead on this signal emission. My friend suggested implementing a function on Object for setting a flag before it could emit the signal ( |
Some further testing with the I'm still interested in patching this PR to address its performance of it (via a hypothetical |
c95c9dc
to
2b51762
Compare
2b51762
to
0bbba18
Compare
Closes godotengine/godot-proposals#7441