Effects: The "Undo" Button for Your Island’s Logic
Effects: The "Undo" Button for Your Island’s Logic
So you’ve written some Verse code. You’ve changed a variable, spawned an item, or dealt damage. But what happens if something goes wrong? What if a player triggers a trap that accidentally deletes the map because you forgot to check their health first?
In Verse, Effects are the safety nets, the rollback buttons, and the logic gates that keep your island from turning into a glitchy mess. They tell the engine how a piece of code behaves when things go right, and more importantly, when they go wrong. Without understanding Effects, your code might compile, but it will likely break your game in ways you didn’t intend.
What You'll Learn
- What Effects are in Verse (and why they aren’t just particle systems).
- The difference between
no_rollback(permanent actions) andtransacts(undoable actions). - How to use
transactsto protect your island’s state using a "Time Travel" analogy. - How to build a simple "Revenge Trap" that cleans up after itself if it fails.
How It Works
Let’s strip away the jargon. In programming, an Effect is a tag you put on a function (a block of code that does something) to describe its behavioral consequences.
Think of Effects like the rules of engagement in Fortnite:
no_rollback(The Default): This is like shooting an arrow. Once it leaves the bow, it’s gone. You can’t "un-shoot" it. In Verse, if you don’t specify an effect, your code assumes it’s permanent. If your code changes a variable or spawns an item, the engine assumes you really want that to happen, forever.transacts(The Save/Load Point): This is like reloading a checkpoint. If you perform an action marked astransacts, the engine remembers the state before the action. If the action fails (throws an error, or returns a failure result), the engine can "roll back" the changes, as if they never happened. This is crucial for things like health checks, inventory management, or complex traps where you don’t want partial states lingering.
Why Do You Care?
Imagine you’re building a trap. You want to:
- Check if the enemy is in the "Critical Health" zone (low HP).
- If yes, explode them.
- If no, do nothing.
If you don’t use transacts correctly, and your check fails in a weird way, you might end up with an explosion that didn’t happen, but the trap is now broken, or a variable stuck in a weird state. transacts ensures that if the "Critical Health" check fails, the game state remains exactly as it was before you even looked at the enemy’s health.
The "Failure Context"
This is the fancy term for "where you can use rollback." Only functions marked with transacts can be used in a Failure Context. A failure context is any place where your code might fail and needs to be undone. If you try to use a transacts function inside a no_rollback block, Verse will yell at you. It’s like trying to use a save point in a level that doesn’t allow saving.
Let's Build It
We’re going to build a "Regret Trap."
When a player steps on this trap, the island will try to deal damage to them. But, we want to ensure that if the damage calculation fails (for whatever reason—maybe the player is invincible, or the math goes weird), the trap doesn’t leave behind a half-executed mess. We’ll use transacts to make the damage attempt "undoable."
The Setup
- Place a Trigger Volume in your island.
- Place a Prop Mover or just use the Trigger’s output to call a Verse script.
- Create a new Verse script named
RegretTrap.
The Code
Here is the core logic. Notice the <transacts> tag on the function signature.
# RegretTrap.verse
using { /Fortnite.com/Devices }
using { /Fortnite.com/Components/Interaction }
# This is our custom function.
# The <transacts> tag means: "If this function fails, undo any changes it made."
# Think of it as: "Try to damage, but if you can't, pretend we never tried."
DamagePlayer(Player : Player)<transacts> : void =
(
# We attempt to deal damage.
# If this line fails (e.g., Player is invalid, or damage is blocked),
# the entire function "rolls back" to the state before it was called.
Player.Damage(50.0)
)
# This is the event that runs when someone interacts with the trigger
OnInteracted(Trigger : Trigger, Player : Player) : void =
(
# We call our damage function. Because it has <transacts>,
# it’s safe to call here. If it fails, the game state is clean.
DamagePlayer(Player)
)
Walkthrough
-
DamagePlayer(Player : Player)<transacts> : void:- This defines a function named
DamagePlayer. - It takes a
Playeras input. <transacts>: This is the key. It tells the Verse compiler, "Hey, this function might change state, but if it fails, I want you to roll it back.": void: It doesn’t return a value (like a health number); it just does something.
- This defines a function named
-
Player.Damage(50.0):- This is the action. It tries to deal 50 damage.
- If this succeeds, great. The player takes damage.
- If this fails (e.g., the player is in a safe zone, or the function is called incorrectly), the
transactseffect kicks in. The engine says, "Oh, that failed? Okay, I’ll revert any side effects from this call." SinceDamageis the only thing happening, the "revert" is just... nothing happened. The player is safe.
-
OnInteracted(...):- This is the event handler. When the trigger is activated, it calls
DamagePlayer. - Because
DamagePlayeris markedtransacts, we can safely call it here. If the damage logic is complex and fails halfway through, thetransactseffect ensures the island doesn’t get corrupted.
- This is the event handler. When the trigger is activated, it calls
Why Not Just Use no_rollback?
If you removed <transacts>, the function would default to no_rollback. This means if Player.Damage threw an error after partially executing some internal logic (which is rare but possible in complex systems), the island could be left in a broken state. transacts is your insurance policy.
Try It Yourself
Challenge: Modify the RegretTrap to include a health check.
Create a new function CheckAndDamage that:
- Takes a
Player. - Checks if the player’s health is above 0 (they are alive).
- If alive, calls
DamagePlayer(from the previous example). - If not alive, does nothing.
Hint: You’ll need to use a conditional (if) inside your transacts function. Remember, if the entire function is transacts, the rollback applies to the whole block. If the player is dead, the function should just "succeed" without doing anything, leaving the game state unchanged.
Hint 2: You can access health via Player.GetHealth().
Recap
- Effects define how a function behaves when it fails.
no_rollback(default) means actions are permanent.transactsmeans actions can be undone (rolled back) if the function fails.- Use
transactsfor critical logic like damage, inventory changes, or state updates where you don’t want partial failures corrupting your island.
References
- https://dev.epicgames.com/documentation/en-us/uefn/verse-glossary
- https://dev.epicgames.com/documentation/fortnite/verse-glossary
- https://dev.epicgames.com/documentation/fortnite/verse-api/fortnitedotcom/itemization/fort_item_pickup_interactable_component/oninteractionsucceeded
- https://dev.epicgames.com/documentation/fortnite/verse-api/fortnitedotcom/devices/service_station_device/damage
- https://dev.epicgames.com/documentation/fortnite/verse-api/fortnitedotcom/devices/roly_poly/damage
Verse source files
- 01-fragment.verse · fragment
Turn this into a guided course
Add Effects to your free study plan — we'll suggest related pages and stitch the lot into one compile-checked, self-guided lesson with worked examples and quizzes.
References
Original tutorial generated by Verse Island from the Verse/UEFN knowledge base, with references to the Epic Games sources above. Code is validated against the knowledge base.