Description
Describe the project you are working on
Godot
Describe the problem or limitation you are having in your project
Godot 3.x had visual scripting, but Godot 4.0 removed this. This is ultimately a good thing, because it would be better to bring it back as a GDExtension in the future.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
Provide an official visual scripting system. See below for details.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
I am here to propose an 8-part plan to bring back visual scripting to Godot to ensure the system is broadly useful in lots of ways, including GLTF interoperability, extensibility, and of course, ease of use. These 8 parts are guiding principles as opposed to steps that can be taken one at a time.
1. Not a part of the engine
Visual scripting should be done with GDExtension. It should not be a part of the engine for several reasons:
- Bloat: Many users do not want visual scripting. Especially considering we may want many high-level blocks, it's better to not burden the main repo with all of that custom behavior.
- Extensibility: Of course we will want to allow writing custom script blocks in GDScript, but users may want to customize the visual scripting system's C++ code. This is much easier if it's done in GDExtension.
- Independent development: This will allow the visual scripting system to be developed and updated independently of the engine. This way users don't need to wait for newer Godot versions to get new visual scripting features.
2. Speed is not vital
Of course, we don't want to make the visual scripting system be purposefully slow, so we should write it in a language like C++ or possibly Rust. But we need to ensure the visual scripting system is primarily high code quality, not high performance.
Depending on the operations you do, GDScript is about 5 to 20 times slower than C++, or about 2 to 10 times slower than C#. Big Godot projects may have hundreds of GDScript files, some of them may have hundreds or thousands of lines. However, GDScript is still fast enough for most users. Visual scripting would be used with much simpler scripts than GDScript, so it doesn't need to be as fast as GDScript.
Knowing this, even if visual scripting was 100 times slower than C++, that is still plenty fast. We should primarily target code quality and easy extensibility over performance.
3. Allow extending in GDScript
Visual scripting needs to be easy to extend. On a 2-person team of 1 artist and 1 high-level GDScript programmer, the GDScript programmer may wish to provide APIs for visual scripting to use.
Therefore we need to ensure it's easy to extend. We need to allow extending visual script block classes with virtual callback methods. We should also ensure the internal code quality is high, to allow users to extend the C++ code if needed.
Still, allowing extending in GDScript should not come at the cost of the performance of built-in script blocks. Having to allocate a Godot Object
for every script block to allow exposing it would be quite slow and memory-intensive at runtime. Instead, all of the built-in blocks should be use lightweight structs to store the data internally, and we have a more complex "extension" block class that uses Godot Object
(or possibly RefCounted
?) to allow extending in GDScript. This does not hurt code quality while being a big win for performance.
4. Provide entire Godot API
One of the big problems with VisualScript in Godot 3.x is that it was missing some critical functionality, like setting values in Arrays. All operations available in GDScript should also be available in visual scripting, although not always exactly the same (ex: since visual script blocks can have multiple outputs for item in array:
visual script blocks can provide both the index and the item).
Aside from that, we should ensure that every API call available in Godot is accessible via the visual scripting system. Every method needs to be callable, every property needs to be accessible, every class needs to be instantiable, etc.
5. Provide high-level blocks
In order for visual scripting to be useful for users to write complex scripts without their canvas turning into a mess of blocks and wires, we need to provide high-level script blocks. These are concepts that may not even make sense to have in GDScript.
For example, let's say we want a high-level script block to get the material properties of an object. The material properties may be located on the MeshInstance3D node, or on the Mesh resource contained in it. In GDScript you would have to check if the MeshInstance3D node is valid, check if it has material properties, check if it has a Mesh resource, check if that has material properties, etc. All that is just to find the material, then you would need to check if it's a BaseMaterial3D and grab each of the properties you need from it, like albedo color, roughness, etc. The high-level visual script block would be much simpler: It takes in an object, and it has many output ports for each of the properties on the material, all the processing to get those outputs is internal to the high-level script block. This does not make much sense in GDScript because on the level of GDScript you really do care about the fine details like where the material is located and what type the object is. It also does not make much sense in GDScript because all of those output ports would simply not work, GDScript functions do not have multiple return values and even if they did that would severely clutter your script with unused variables.
6. Learn from existing successes
A visual scripting system would be incomplete without getting experienced Unreal Blueprints users to participate in its development. Tons of people have a great time using Unreal Blueprints, we need to ensure we have all of the features that Unreal users are currently using to make successful AAA games using Blueprints (that doesn't imply that visual scripting will enable AAA games of course, just that your choice of scripting language should not limit you).
Unreal is of course not the only engine with a visual scripting system, but it is the most popular. We can learn from the successes of visual scripting in other engines as well.
EDIT: I have just been made aware that Godot Orchestrator exists https://github.com/Vahera/godot-orchestrator so this will either be a great source of inspiration or a great base.
7. Interoperability with GLTF interactivity
The Khronos group is working on an engine-agnostic scripting system in GLTF. This is super cool. Imagine being able to export a script from Godot and import that into Unreal, or export a script from Unreal and import that into Godot. Or imagine using Godot as a "game asset SDK" where you can write a simple behavior script in Godot and that can be imported at runtime into a "metaverse" style game, such as V-Sekai or The Mirror, two platforms made in Godot, without the security and portability concerns of just sending a Godot scene file with GDScript in it.
I think it would be a great idea to design our future visual scripting system to be compatible with GLTF interactivity to the greatest extent possible. This includes both import and export.
Of course, the Godot visual scripting system will need to be a superset of GLTF interactivity, as there will be many concepts in Godot that can't be available in an engine-agnostic format, and we will probably need to write code to "compile down" high-level blocks into simpler ones. But still, we should be able to export most simple behavior scripts, or most features of complex scripts, or import scripts from GLTF into Godot. This is good enough to cover lots of use cases. For complex scripts being brought between engines, if 10% of the visual script blocks do not survive the trip, that still means 90% did survive, and then it's easier to manually fill in the gaps instead of starting from scratch.
To be clear, the below image has nothing to do with what the proposed UI will look like. This is just an abstract representation of the interactivity graph data.

Work-in-progress GLTF interactivity PR: KhronosGroup/glTF#2293
8. Timeline
There is not really any rush in completing this, and in fact, it may be better to wait for several reasons.
For the goal of interoperability with Khronos GLTF interactivity, it would be helpful to wait for the Khronos group to finish standardizing that so we have a good base standard to structure visual scripting around.
For making an editor, @Geometror has been refactoring the GraphEdit system over the past year or so. It would be helpful to wait to work on the visual scripting system until the GraphEdit refactor is done, so that we will not need to redo the editor code to use the new GraphEdit APIs. You can view some of his excellent work here: https://github.com/godotengine/godot/issues?q=author%3AGeometror+label%3Atopic%3Agui+
For actually implementing, there are still some bugs and limitations with GDExtension that would be helpful to have fixed first. I don't have any specific bugs immediately in mind that are blocking visual scripting (since I have not started this, I have not run into them yet) but I know that there are many bugs and we will run into them at some point.
There are still other areas that are a much higher priority for engine contributors to work on. Of course since this will be done in GDExtension, the development cycle is not tied to the engine, but this will very likely be done by existing engine contributors (as evidenced by few people stepping up to maintain VisualScript in Godot 3.x). I would rather the engine contributors spend their time for now on important bug fixes than chase after a new shiny thing. I am personally interested in working on this, and I have lots of experience with developing a visual scripting system thanks to my time at The Mirror, but it is not a high priority for me.
I would expect that this visual scripting system could be completed sometime in the late 2020s (remember it is already 2024), but it is hard to say if that will be 2026 or 2029. Regardless I want to ensure we take the time do this right, and I have no plans to start working on this at all in 2024 due to all of the above reasons.
If this enhancement will not be used often, can it be worked around with a few lines of script?
No.
Is there a reason why this should be core and not an add-on in the asset library?
This should be an add-on in the asset library! An officially endorsed one.