godotengine / godotengine/godot-visual-script
Better custom visual script node API?
- Dominant language
- C++
- Stars
- 131
- Forks
- 25
- PR merge metrics
- No merged PRs in 30d
Description
In the event that visual scripting doesn't get a massive, paradigm-shifting overhaul, I'd like to leave some feedback here about the current solution, as a programmer:
In $PROPRIETARY_ENGINE, I was able to follow a pattern of writing low-level systems in $LANGUAGE, and connecting to them with higher level, custom written nodes for a more plug-and-play method of implementing high level game logic, tying events to actions without awkward inspector-based solutions, etc. I won't go into the pros/cons of this approach here.
When I tried to replicate the same workflow in Godot, I found that the custom VS node API was pretty awkward. The heavy reliance on an array-based API for mapping names/types to ports is incredibly unwieldly and slowed down iteration a lot. Code like this looks acceptable at a glance, but once you blow it out to 3, 4 ports? For most of the nodes you'll end up making? And having to keep track of what input type and name lives at what index a month down the road, spread across several different functions? Not great.
```gdscript
## Snippet of official API
# The types of outputs per index starting from 0.
func _get_output_value_port_type(idx):
return TYPE_VECTOR2
```
(For reference, the current custom visual script node API is documented here: https://docs.godotengine.org/en/3.5/tutorials/scripting/visual_script/custom_visualscript_nodes.html)
Code speaks better than words in this case, so an example of a better API, from my perspective:
```gdscript
# Example of a "Can Walk In Direction" node.
# Accepts directional input, outputs a boolean as well as two output flows,
# If GDSCript supports custom decorators...
@input_value_port("Direction") var direction_input: Vector2
@output_value_port("Can Walk") var can_walk_output: bool
@output_flow_port("Can Walk") var can_walk_flow: Flow
@output_flow_port("Can't Walk") var cannot_walk_flow: Flow
# If no custom decorators, or a decorator-based workflow is undesirable...
func _ready():
direction_input = register_input_value("Direction", TYPE_VECTOR2)
can_walk_output = register_output_value("Can Walk", TYPE_BOOLEAN)
# etc ...
func _step(start_mode, working_mem, other_params_no_one_uses):
var can_walk = Map.can_walk_in_direction_no_pathfinding(direction_input.input)
can_walk_output.output = can_walk
if can_walk:
# Any nodes connected to the "Can Walk" flow are activated.
can_walk_flow.activate()
else:
cannot_walk_flow.activate()
```
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.