Most patches in Patchworld are made of static, hand-wired connections: you grab an output, drag it onto an input, done. But many gameplay ideas need the set of blocks itself to evolve at runtime - enemies that spawn on the fly, picked-up items, players that join and leave, projectiles that exist only for half a second...
Dynamic patching is the toolkit you reach for when you cannot (or do not want to) hard-wire every reference. It is built around a small family of System blocks that produce, filter and iterate over lists of blocks:
If you have not read it yet, the Variable System wiki page is the perfect companion to this one: variables are the most common way to "remember" what you spawned and re-find it later.
Three building blocks are enough to express most dynamic patches:
block_spawn's "All copies", Ray Cast's "Hit Results", All With Variable's "Output", Trigger Box's output, etc.block_compare (set ops, last/first, parent, grabber...) and / or all_with_variable (filter by value, sort).block_foreach, then chain the foreach's "Output block" into Tag inputs of blocks like Set Position, Block Set Color, Set Scale, set_variable, block_remove, etc. Use the "Index" jolt output to drive per-instance variation.Tip: drop a Get Name Text anywhere on a Tag output you suspect is wrong - it prints the block names of whatever is currently passing through, which is the easiest way to debug a dynamic patch.
block_spawn and block_foreach are designed to work together. The spawn block already exposes its instances on the "All copies" tag output, so it plugs straight into a foreach Input.
A minimal "spawn 10 cubes in a row" patch:
[ trigger ] -- 10 ---> [ block_spawn ] -- All copies ---> [ block_foreach ]
^ |
| | Output block
[ template:cube prefab ] v
[ block_set_position ]
[ block_foreach.Index ] --> X knob (or via Math)
Steps:
block_spawn's "Template to spawn".block_foreach.block_set_position Target.block_set_position. Each cube ends up at a different X.With this pattern, anything you connect downstream (color, scale, variables) is applied per-copy without ever touching the spawned blocks by hand.
A better, more decoupled version of the same idea is to tag spawned blocks with a variable and let the rest of the patch react to the tag, not to the spawn block itself:
[ block_spawn ] -- All copies --> [ set_variable "IsEnemy" = 1 ] (Input)
[ all_with_variable "IsEnemy" ] -- Output --> [ block_foreach ] --> ...gameplay...
Why this is nice:
remove_variable "IsEnemy", and the foreach automatically forgets it.all_with_variable's Value Filter and Order in output to build leaderboards or priority queues for free.See Variable System for the full details.
block_spawn is one source of dynamic blocks; detection is another. Ray Cast outputs the blocks its ray hits, Trigger Box outputs blocks entering a region, Block Compare with Grabber outputs the controller currently holding a block. All of these produce live lists you can plug into a foreach or store with block_compare "Store".
Example: damage every block hit by a sphere cast.
[ raycast (Continuous, thickness > 0) ] -- Hit Results --> [ block_foreach ] --> [ set_variable "HP" -= 1 (additive) ]
block_compare shines when you need to know what differs between two lists.
Common combinations:
A-B with A = "current frame raycast hits" and B = "previous frame hits stored in a Store-mode block_compare" gives you the newly entered blocks.Shared between two raycasts coming from each hand tells you which block is grabbed by both hands.== between an All With Variable result and a hand-picked Tag input fires a single jolt when "everything is collected".Last / First are the simplest way to pick a single block out of a dynamic list (e.g. the most recent hit).Device / Parent let you escalate from a clicked sub-part to the surrounding Device, which is the unit you usually want to act on (e.g. respawn the whole rifle, not just one of its sub-parts).Grabber maps a list of grabbed blocks to the controllers grabbing them - perfect for haptics or scoring "who picked what first".Store keeps an accumulating list as A flickers; combine with the Clear jolt to reset.Index uses the Manual Trigger jolt value as an index into A; great in combination with a Counter or with a block_foreach's Index output.Anything you spawn dynamically should usually be removed at some point - either when a condition is met (player dies, level ends) or after a delay.
Two approaches:
block_spawn before triggering. Patchworld auto-destroys each copy after N seconds. Simplest, no extra wiring.all_with_variable, raycast hits...) into block_remove's Input, then fire the Remove jolt. Useful when removal depends on gameplay events rather than time.When the blocks you spawned are full Devices (e.g. a Group containing a body + colliders + behaviour), tick Use Device on Input on block_remove, otherwise only the connected sub-block is removed and you leak the surrounding Device.
Inside a freshly-spawned Group/Device you often want behaviour that talks back to the rest of the world (e.g. "this enemy reports being killed"). Two complementary tools:
LastHit, HP, Owner, etc., even with the same variable name.The two patterns combine well: a spawned enemy uses set_variable for per-instance state and wireless_out_jolt for global "I died" notifications.
block_spawn has an inspector option "Use TextInput as spawn command". When ON, instead of cloning the connected template block, it reads the text on a Txt (or any block exposing a TextInput) connected to the template input and treats it as one of:
oscillator, make_physical, block_set_position...),spawn mesh src:"https://...").Combine with a Contain Text to dispatch on user-typed strings, or with Join & Apply Text to assemble a command from several sources. This is how asset-library-style patches work without leaving the world.
Dynamic patches are notoriously harder to debug than static ones because the wires you see in the editor are not the whole picture. A few habits help a lot:
block_compare's "Output Count" and all_with_variable's "Count" jolt outputs re-fire whenever the lists change; route them into a Number Readout or Number to see the size live.| Need | Block | Thumbnail |
|---|---|---|
| Clone a block / Device on demand | Block Spawn | |
| Iterate over a list of blocks | Block Foreach | |
| Filter / combine / navigate lists | Block Compare | |
| Destroy blocks (with optional delay) | Block Remove | |
| Tag blocks at runtime | Set Variable | |
| Read a tag from a block | Get Variable | |
| List every block with a tag | All With Variable | |
| Detect blocks via collisions / vision | Ray Cast, Trigger Box | |
| Send jolts without wires | Send Jolt, Receive Jolt | |
| Build / dispatch text commands | Txt, Contain Text, Join & Apply Text | |
| Debug a Tag output | Get Name Text | |
| Conditionally pass or block a Tag connection | Tag Gate |
Tag Gate sits between a Tag source and a Tag destination. When the gate is On the reference passes through; when Off the downstream block sees an empty list.
[ all_with_variable "Enemy" ] --> [ Tag Gate ] --> [ block_foreach ] --> [ Set Scale ]
^
[ metronome / compare output ]
This is useful when you want to temporarily suspend an effect without cutting the wires — for example, freezing all enemies while a cutscene plays, or toggling an entire gameplay system on/off with a single jolt. Combine with a Gate (jolt version) for the equivalent control over Jolt signals.