Coral the flamingo has been watching you stack up wins on South Shores: you can wire a button, push a HUD message, count shells in a var, and keep your functions to one responsibility each. Today she struts up with something shiny tucked under one wing — a golden shell — and your first real taste of object-oriented Verse. You'll write a base shell class, then a golden_shell subclass that uses the <override> specifier to change what happens on pickup, while the collection code never has to know which shell it just handled. That trick has a grown-up name — polymorphism — but on this beach we just call it "the rare one plays by richer rules."
What you will build
The Shell-Hunt capstone (lesson 17) needs one rare golden shell worth 3 points with a bonus effect, collected through the same code path as every ordinary shell. That's exactly what you build here:
- A base
shellclass with anOnCollected() : intmethod — the ordinary 1-point pickup. - A
golden_shellsubclass that marksOnCollected<override>()to return 3 points and fire a sparkle VFX burst. - A collector device that keeps every shell in one
[]shellarray and callsOnCollected()without a singleif this is goldencheck.
When Shell-Hunt's CollectShell() handler later scoops up whatever the player found, the golden shell quietly does its own thing — no special cases, no duplicate wiring.
Walkthrough
Step 1 — Place the devices
In your South Shores project:
- Place a Button device on the sand (our stand-in for "player grabbed a shell" — lesson 4's trigger zones take over in the capstone).
- Place a HUD Message device to announce the running score.
- Place a VFX Spawner device set to a burst effect — the golden shell's little firework moment.
- Create a new Verse file (
shell_collector.verse), paste the code below, build, and wire the three@editableslots in the Details panel. TheGoldenShellslot expands so you can point itsSparkleVFXat the VFX Spawner.
Step 2 — The code
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# ── Base class: an ordinary beach shell, worth 1 point ──
shell := class:
# Every shell knows how to be collected. Returns the points earned.
OnCollected() : int =
Print("Shell collected: +1 point")
1
# ── Rare subclass: the golden shell — 3 points and a sparkle burst ──
golden_shell := class<concrete>(shell):
@editable
SparkleVFX : vfx_spawner_device = vfx_spawner_device{}
# <override> replaces the base behaviour — same name, same signature.
OnCollected<override>() : int =
SparkleVFX.Restart() # burst-mode VFX celebrates the rare find
Print("GOLDEN shell: +3 points!")
3
# ── The collector device placed on the island ──
shell_collector_device := class(creative_device):
@editable
CollectButton : button_device = button_device{}
@editable
ScoreHUD : hud_message_device = hud_message_device{}
@editable
GoldenShell : golden_shell = golden_shell{}
var Score : int = 0
var NextShell : int = 0
var BeachShells : []shell = array{}
OnBegin<override>()<suspends>:void =
# One array, mixed types — the golden shell hides among plain ones.
set BeachShells = array{shell{}, shell{}, GoldenShell, shell{}}
CollectButton.InteractedWithEvent.Subscribe(OnCollect)
# ONE shared collection path for EVERY shell type.
OnCollect(Agent : agent) : void =
if (Found := BeachShells[NextShell]):
Points := Found.OnCollected() # dispatches to the REAL type
set Score += Points
set NextShell += 1
ScoreHUD.SetText(ScoreMsg(Score))
ScoreHUD.Show(Agent)
ScoreMsg<localizes>(Points : int) : message = "Shells banked: {Points} points"
Step 3 — Line by line
| Lines | What's happening |
|---|---|
shell := class: |
The base class. No specifier needed — Verse classes can be subclassed by default. |
OnCollected() : int = ... |
The base behaviour: print a message, return 1. In Verse the last expression in the body is the return value, so that lone 1 is the point payout. |
golden_shell := class<concrete>(shell): |
The subclass. (shell) says "golden_shell IS a shell"; <concrete> lets it carry @editable fields the editor can wire. |
@editable SparkleVFX : vfx_spawner_device |
The bonus effect's device reference lives on the subclass — plain shells don't pay for hardware they never use. |
OnCollected<override>() : int = ... |
The star of the lesson. <override> replaces the base method with golden behaviour: Restart() triggers the burst VFX, and 3 is returned instead of 1. The signature must match the base exactly. |
var BeachShells : []shell = array{} |
The array is typed as the base class, so both shell{} and the golden subclass fit inside — one bucket, mixed types. |
Found.OnCollected() |
The payoff. Found is typed shell, but Verse dispatches to the method of the object's actual class at runtime. Plain shell → 1. Golden shell → sparkles and 3. The caller can't tell and doesn't care. |
set Score += Points / ScoreMsg<localizes> |
Your lesson-5 counter and lesson-6 interpolated HUD string, unchanged. New skills stack on old ones — nothing gets thrown away on this island. |
Step 4 — Test it
Launch a session and press the button four times. The first two presses bank 1 point each. The third press is the golden shell: the VFX bursts and the HUD jumps by 3. The fourth banks 1 again. Notice what you did not write: OnCollect has zero golden-shell logic in it. The subclass carried its own rules into the shared path — that's polymorphism doing the lifting.
Common patterns
Pattern 1 — Override the data, inherit the behaviour
Sometimes the subclass only changes a number, not the logic. Verse lets you override a field with <override> and keep the inherited method, which now reads the new value:
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
beach_shell := class:
Points : int = 1
OnCollected() : int =
Print("Collected: +{Points}")
Points
golden_beach_shell := class(beach_shell):
# Override the DATA, inherit the behaviour.
Points<override> : int = 3
field_override_demo_device := class(creative_device):
OnBegin<override>()<suspends>:void =
Shells : []beach_shell = array{beach_shell{}, golden_beach_shell{}}
for (S : Shells):
S.OnCollected()
golden_beach_shell never redefines OnCollected — it just swaps Points to 3 and the inherited method does the rest. Smallest possible subclass, same polymorphic payoff.
Pattern 2 — Tally a whole beach polymorphically
The capstone will ask "how many points is this beach worth?" One loop over the base type answers it, no matter how the rares are sprinkled in:
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
tide_shell := class:
OnCollected() : int = 1
golden_tide_shell := class(tide_shell):
OnCollected<override>() : int = 3
tide_pool_tally_device := class(creative_device):
OnBegin<override>()<suspends>:void =
Beach : []tide_shell = array{tide_shell{}, golden_tide_shell{}, tide_shell{}}
var Total : int = 0
for (S : Beach):
set Total += S.OnCollected()
Print("This beach is worth {Total} points")
Add a pearl_shell worth 10 tomorrow and this tally code doesn't change by one character. That's the extensibility you're buying with <override>.
Where this goes next
- Lesson 16 — Powerup Pickups upgrades the golden shell's bonus effect from a sparkle to a real speed powerup, so finding the rare one makes you faster at finding the rest.
- Lesson 17 — the Shell-Hunt capstone drops your
shell/golden_shellpair into the full 90-second beach scavenger: Verse-spawned bobbing shell props, trigger-zone pickups, and one sharedCollectShell()handler that calls exactly theOnCollected()you wrote today. The capstone also imports your ShellHuntKit module from lesson 9 — so keep these classes tidy; they're about to become residents.
Coral's parting wisdom, delivered on one leg: "When the rare one shows up, don't rewrite the beach — just let it override the rules."