Are you sure there is no
_set() in parent class? That's declared in
Object, and I thought everything inherited that.
You can get all property names (including ones you designed, also exported variables) from a node by calling
get_property_list(). This returns a big set of dictionaries with a lot of metadata for each property.
(One would extract the names like this:)
var names := 
for item in long_list_of_dictionaries:
I wrote a custom
_set() to help answer this question, observing the manipulated property list to handle the expected behavior of
_set() while also extending it:
func _set(property: String, value) -> bool:
if !(property in property_list): # property_list is a global variable
print("property %s is not in property_list" % property)
print("emitting property changed signal now")
emit_signal("PropertyChanged", property, value);
FWIW, this is my signal declaration:
signal PropertyChanged(property, value)
This gives me a way to emit signals when I call
_set(); but only when
_set() is explicitly called, i.e.
scale *= 2.0 does not call it or emit the signal. This isn't great because
_set() necessitates passing strings around instead of property references, so Godot has to go do lookups based on what strings you pass it.