General design overview
Before we dive deep into these findings, the main characteristics of Noodle will be briefly described. Noodle will be diagram-based [1], [4] which means that the language is graph-based and the execution can be followed by traversing nodes. As my research shows, this is the most commonly used VSL form in game engines, e.g., in Unreal Engine, Unity and Godot [5]–[8]. A popular alternative is the block-based design. A block-based design is used for Scratch and Google’s Blockly [9]–[11] but it is not often used in games. Moreover, Noodle will offer pure nodes, nodes without side effects and nodes that may have side effects [12]. They are differently identified by either having an “execution” wire/connection or just a data flow connection. This allows the dialect designer to decide if they need support for one of these concepts or both, depending on the use case requirements. On its own, the language is not event-based, so a graph can be triggered at any node at any point in time by the runtime. However, the dialect designer can specify nodes that can be triggered. These nodes can be used as entry points which would allow an event-based structure if needed. All these decisions are based on what is common in tools used in the game industry, be it Godot’s visual scripting or Unreal Engine’s Material Editor [8], [13]–[17].
Noodle’s design idea of being a composable language that one can shape depending on the users’ needs, or how literature would call it “extending” by being an extension language, is greatly inspired by the works of Hisham Muhammad and Roberto Ierusalimschy in their paper about the used API design of the Lua programming language [18]–[21]. Since we are talking about a visual scripting language which logic is expressed in composing visual elements [22], we need some form of specification. In Noodle the dialect is described via a protocol: what nodes it supports, what kind of types are supported, etc. Moreover, Noodle supports internal modules, i.e., subgraphs that can help organizing your graph, as well as external modules, if a module resolve function is provided. If not, only internal modules will work. However, the defined protocol might differ from dialect to dialect, depending on the use of the language. We will talk about the protocol an its uses later.