Nested Prefabs
Before this: Lifecycle and Storage
Next steps: One Chip per Player
A spawned copy is a full program, so it can spawn copies of its own. This lesson places a turret that fires a shot every second. The turret is a prefab, and the shot is a prefab inside it.
Contents
zone "Zone Ref" -> chip pad
button Held -> chip clear
Code
@left in pad: zone
@left in clear: exec
on ZoneEntered(zone = pad) -> (character) {
SpawnPrefab(
prefab = $```
@label("Turret")
on Clock(interval = 1.0) {
SpawnPrefab(
prefab = $```
@label("Shot")
on Clock(interval = 0.05) {
let grid = ReadBrickGrid()
grid.SetLocation(grid.GetLocation() + Vec(0.0, 20.0, 0.0))
}
```,
offset = Vec(0.0, 0.0, 30.0),
lifetime = 3.0,
limit = 10
)
}
```,
offset = Vec(0.0, 200.0, 50.0),
limit = 1,
destroyAll = clear
)
}
Three programs, one inside the next:
- The spawner places one turret 200 units to the side of itself when
someone steps on the pad (
limit = 1, so there is never more than one). - The turret has no events to wait for. Its clock starts when it appears, and every second it spawns a shot 30 units above itself. An offset is measured from the Spawn Prefab gate that uses it, and this one sits in the turret, so the shots start at the turret wherever it is.
- The shot moves itself 20 units along the world’s Y axis every
twentieth of a second, and its lifetime removes it after 3 seconds.
ReadBrickGrid()inside a copy is the copy’s own grid, andSetLocationmoves a spawned copy.
The clear button removes the turret. What happens to the shots already in
the air?
Run
- Compile the chip and paste it in-game. Give a brick an Attached Zone for the pad and place a Button beside it.
- Wire the Zone Ref to
padand the Button’s Held toclear. - Step on the pad. A Turret chip appears, and a Shot chip rises out of it every second and flies off.
- Press the button while shots are flying.
Under the Hood
The spawner’s save holds the turret, and the turret holds the shot, so one compile packs both levels. Only the spawner has a pin. The turret and the shot run on their own.
The turret’s Spawn Prefab gate belongs to the turret, so limit = 10
counts the shots that one turret has made, and the spawner’s clear reaches
only what the spawner’s gate made: the turret. Shots already in the air were
made by the turret’s gate, not the spawner’s, so expect each one to go when
its own 3 seconds run out.
Prefabs can nest up to 8 levels deep, inline or as files.
As files
The same three programs as files, with the shot in a subfolder:
spawner.ws
turret.ws
parts/shot.ws
spawner.ws references $./turret.ws. Inside turret.ws:
@label("Turret")
on Clock(interval = 1.0) {
SpawnPrefab(
prefab = $./parts/shot.ws,
offset = Vec(0.0, 0.0, 30.0),
lifetime = 3.0,
limit = 10
)
}
A path inside a prefab file is read from that file’s folder, not the
spawner’s. Here the two are the same folder, but move turret.ws into
parts/ and its reference becomes $./shot.ws, while spawner.ws changes
to $./parts/turret.ws. Compiling spawner.ws builds all three, as in
Prefab Files.
Modify
- Fire the shots straight up instead: which numbers in the shot change?
- Give the turret a second clock that fires a second kind of shot, slower and longer-lived, every three seconds.
- Make the shot fall: each pulse, also lower it a little more than the last
time. Keep the drop so far in a
varinside the shot.
Make
Make a fountain: a pad places a fountain that, every half second, spawns a
drop going up. Each drop rises for a second, then falls for a second, then
removes itself with DestroySpawnedPrefab(). A button clears the fountain.
zone "Zone Ref" -> chip pad
button Held -> chip clear
Good to Know
destroyAllremoves what its own gate spawned, not what those copies spawned in turn. Give inner prefabs alifetime.- Every level carries the levels inside it. A large shot makes the turret large, and the turret makes the spawner large.
- A path inside a prefab file is relative to that file.
See Prefab References in the reference.
Next: One Chip per Player.