-
-
Notifications
You must be signed in to change notification settings - Fork 21.6k
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
C#: Generators ignore _Ready method in partial classes from another generators #66597
Comments
Does it work if the method is declared as partial? public partial class MyNode : Godot.Node
{
public override partial void _Ready();
} |
That's actually a good idea. Is it a workaround or we can require developer to add it somehow? Interface? Error from the generator? |
When the game developer doesn't implement the engine callback methods (e.g.: To know which methods are implemented, Godot's source generators generate a method that is called once to retrieve the list of implemented methods that are callable/interoperable with the engine (engine callbacks, methods that only use supported marshable types). Because of this, we don't want developers to implement a I think the best option would probably be to document this behavior and recommended source generator developers to use |
Definitely. |
When I was trying to check whether my _Ready method is there, I saw it in generated code. A method called once would notice presence of _Ready method. Can you please elaborate on that? |
I was referring to the generated Either way, because these methods are generated and there is no guarantee on the order of execution of source generators, we can't rely on checking generated code to check if the To explain further, the core implementation of Lines 130 to 155 in 67961d8
The implementation of Footnotes
|
Thanks a lot for such a brilliant explanation! |
Third Party Source Generation ProposalI'd like to propose a potential solution. I believe this solution could solve the following problems:
While this may not be the best solution, I believe any adopted solution should solve all of the problems above. Hopefully this proposal will help spur future ideas, if nothing else. ExplanationWe know that a node can observe all lifecycle events by implementing To make a third-party generator that observes lifecycle events, generator authors can generate a partial implementation for a node script class that contains a method that should be called from // Potential output from a third-party generator...
public partial class SomeNode : Node {
// generated method handler that should be called back.
public void SomeGeneratedNotificationHandler(int what) {
// this will get called on _Notification lifecycle events
// make your generator do whatever it needs to in response
// to lifecycle changes
}
} An official Godot source generator can inject an attribute named The Imagine in the future that @31 has ported their // Your node script class that uses a third-party generator
[Lifecycle("GodotOnReady")]
public partial class MyNode: Node {
// ... your node's code. no other boilerplate except the attribute above.
} The Of course, the hypothetical updated This approach allows multiple source generators to be leveraged that each respond to lifecycle events in a node. // Your node script class that uses third-party generators
[Lifecycle("GodotOnReady", "SomeOtherGenerator")]
public partial class MyNode: Node {
// ... your node's code. no other boilerplate except the attribute above.
} The script above would benefit from two generators that each add methods that respond to the node's lifecycle. All of the third party generator methods would be called in the order they were listed in the By convention, developers would be incentivized to name their lifecycle observation method the same name as their source generator. We can document this convention by adding a page to the C# section of the Godot docs that describe useful tips for building third-party source generators. Naturally, this proposal will require changes to be made to the Godot Source generators. I don't think the changes are too terribly difficult, however. Feel free to rip this apart. If you have any questions or I didn't do a good job explaining, let me know and I'll try to clarify. Credits
-- EDIT: I actually ended up creating a source generator that does most of what I described above, plus additional features that essentially allow you to create node mixins. You can find it here: https://github.com/chickensoft-games/SuperNodes |
Worth keeping an eye on the base .NET issue for dependent source generator support: dotnet/roslyn#57239 Note, I would assume any solutions here will be related to |
I'm more interested in seeing Godot's method dispatcher code changed than leaning into chained source generators. Maybe there's a more intelligent way to conditionally dispatch method calls from C++ instead of the InvokeGodotClassMethod in godot .NET. If the Ready method were defined in a .NET Interface then we'd be able to more naturally delegate Ready dependencies to User and/or Generated code in .NET. |
Godot version
4.0 beta 1
System information
Windows 11
Issue description
This one is kinda tricky.
We have source generators, they analyze classes and list all the methods they find so if there is no
_Ready
or_Process
methods, they don't call it.The problem is, generators don't know about each other, so if there is another generator that populates _Ready method, Godot's generator won't see it and, therefore, it's never get called.
The simplest solution is "just don't generate _Ready method". But it adds extra restrictions for developers when it comes to initialization.
We don't have an access to constructor, so _Ready is the only place we can do initial logic and its generation is crucial for some popular plugins like https://github.com/31/GodotOnReady.
As an another example, generation of _Ready method would be a very tidy and clean way to implement Dependency Injection. In Godot 3.5 I had to hook IL call to
_Ready
method and patch it, but since Godot 4 use Collectible Assemblies, it's not possible anymore. I implemented it using source generation, but it doesn't work, because Godot doesn't call my generated_Ready
method, as I described above.I know that it's not possible for generator to see another one, but probably we could think of a solution for this cases. I can think of using reflections to check
_Ready
method presence and cache it somehow.Thanks.
Steps to reproduce
_Ready
method using C# source generators or add https://github.com/31/GodotOnReadyMinimal reproduction project
No response
The text was updated successfully, but these errors were encountered: