godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91.13k stars 21.19k forks source link

GDScript cannot override Godot's native functions #55024

Closed xsellier closed 1 year ago

xsellier commented 2 years ago

Godot version

4.0.dev 7791599d5bcfdbae0d2a96e5fc13d9021ec820be

System information

Linux binogure 5.14.0-2-amd64 #1 SMP Debian 5.14.9-2 (2021-10-03) x86_64 GNU/Linux

Issue description

I don't know if it is normal, but I cannot override any godot's native functions using GDScript. It never calls the gdscript function but the godot's core function instead.

Steps to reproduce

var __data = {}

func _ready(): set('random_key', 'random value')

func set(key, value): print('Setting a new value') __data[key] = value



The `set` function is never called, and there is no warning/error in godot explaining that is prohibited.

### Minimal reproduction project

_No response_
tx350z commented 1 year ago

Even though it did work as needed in 3.x. At this point it appears none of my 3.x apps, libraries, and tools are upgradable to 4.x.

Zireael07 commented 1 year ago

@tx350z It was a bug/inconsistency that you exploited

dalexeev commented 1 year ago

Even though it did work as needed in 3.x.

In 3.x, this is also not overriding, but shadowing. You're just creating another method with the same name, which is definitely confusing. In 4.0, an additional problem is that even GDScript can't always distinguish between these methods. We could fix this, but it would hurt performance for no good reason, since the behavior in 3.x is still not correct and expected by users ("I've overridden queue_free(), why isn't it called, when the node is removed by the engine?").

Discussion in Rocket Chat ![](https://user-images.githubusercontent.com/47700418/219399685-e66785af-d0e8-484d-a614-590dde1bce12.png) ![](https://user-images.githubusercontent.com/47700418/219400190-fddbe5f6-22b9-45bf-8abb-5ed3f14d5ec9.png)

Duplicate another my comment:


Why it's done:

A few tips:

  1. You can disable or ignore this warning, but correct behavior is not guaranteed.
  2. This warning does not apply to native virtual methods and any custom methods. You can override them.
  3. If you need to customize some engine method, you should create a wrapper with a different name, not "override" it.
tx350z commented 1 year ago

I think I found a solution for my needs in HxGodot. As much as I've come to love coding GDScript, the 4.0 update has too many new barriers to overcome.

MikeSchulze commented 1 year ago

@GodotDevs it an always upcomming topic and you can see the useres want to have the possibility to override a core function.

From technical perspective so far i anderstand, the core change in GdScript 2,0 is instead of calling functions by name you call it via function pointer.

Why you not provide a @override annotation and check when a class is loading to use a function table instead of function pointer to achive it?

YuriSizov commented 1 year ago

@MikeSchulze Again, this didn't work in Godot 3.x either. It is not related to GDScript, it's just how Godot is, and always was. If a method is not made to be overridable, you can't override it, neither from scripting, nor from extensions. The only change in GDScript that is relevant here is that we now tell the user that what they are trying to do is wrong and is not going to work.

There are no plans to allow overriding any core function, because it's impractical from the performance perspective. And once again, this is not a decision of the GDScript team, it's a core decision.

Furthermore, cases like get_class are a different kind of issue entirely. Users don't want to override this method, they were trying to override it because it doesn't work as expected with custom classes out of the box. We need to address the underlying issue here instead of pleading to make the entire core extensible.

sancho2 commented 1 year ago

In 3.x, this is also not overriding, but shadowing. You're just creating another method with the same name,

It is further confusing since the error message you get in 3.5 when you don't match the function signature is:
"The function signature doesn't match the parent" (specifically the Timer method set_wait_time)

Since we can only override virtual native methods, how do we know which native methods are virtual?

KoBeWi commented 1 year ago

Virtual methods all start with underscore (_) and are also labelled as virtual in the documentation.