godotengine / godotengine/godot-visual-script

Better custom visual script node API?

Open
#33 1 comment 1 reaction 0 assignees View on GitHub
enhancement
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.