Reference Devices

mutator_zone_device: Zones That Change the Rules

The mutator zone device carves out a region of your island where the rules change — no building, low gravity, no weapons — and, more importantly for Verse, it fires events the moment a player enters, exits, or emotes inside it. This article shows you how to wire those events to real game logic and how to query and control the zone from code.

Updated
The code on this reference page is provided as-is and did not pass the latest compile check — treat the examples as a starting point and verify in your project.
Watch the Knotmutator_zone_device in ~90 seconds.

Overview

A mutator zone is an invisible box (or cylinder) you place in your level to override gameplay rules inside it — disable building, change gravity, block weapons, force-disable the emote wheel, and so on. Those rule overrides are configured in the device's Details panel in UEFN.

What makes it powerful in Verse is its event surface: it tells you exactly when an agent crosses the boundary (AgentEntersEvent / AgentExitsEvent) and when a player starts or stops emoting inside it (AgentBeginsEmotingEvent / AgentEndsEmotingEvent). On top of that you get query methods like IsInVolume and GetAgentsInVolume, plus runtime control with Enable/Disable and team/class retargeting via UpdateSelectedTeam and UpdateSelectedClass.

Reach for a mutator zone when you want a region with consequences: a safe spawn room where weapons are sealed, a lava pit that damages anyone inside, a dance-floor minigame that scores emotes, or a no-build king-of-the-hill point. The zone enforces the passive rules; your Verse code reacts to who's in it and does the active gameplay.

API Reference

mutator_zone_device

Used to specify a zone where custom gameplay effects can be applied (e.g. gravity, no build, no weapons).

Full public surface, resolved verbatim from the live Epic digest (Fortnite.digest.verse). Inherited members are merged from effect_volume_device.

mutator_zone_device<public> := class<concrete><final>(effect_volume_device):

Events (subscribe a handler to react):

Event Signature Description
AgentBeginsEmotingEvent AgentBeginsEmotingEvent<public>:listenable(agent) Signaled when an agent in this zone begins emoting. This will not signal if the agent is on the Safe Team or if Affects Players is disabled. Sends the agent that started emoting.
AgentEndsEmotingEvent AgentEndsEmotingEvent<public>:listenable(agent) Signaled when an agent in this zone ends emoting. This will not signal if the agent is on the Safe Team or if Affects Players is disabled. Sends the agent that stopped emoting.
AgentEntersEvent AgentEntersEvent<public>:listenable(agent) Signaled when an agent enters this zone. Sends the agent entering this zone.
AgentExitsEvent AgentExitsEvent<public>:listenable(agent) Signaled when an agent exits this zone. Sends the agent exiting this zone.

Methods (call these to make the device act):

Method Signature Description
UpdateSelectedClass UpdateSelectedClass<public>(Agent:agent):void Updates Selected Class to Agent's class.
UpdateSelectedTeam UpdateSelectedTeam<public>(Agent:agent):void Updates Selected Team to Agent's team.
IsInVolume IsInVolume<public>(Agent:agent)<transacts><decides>:void Is true when Agent is in the zone.
GetAgentsInVolume GetAgentsInVolume<public>()<reads>:[]agent Returns an array of agents that are currently occupying the volume.
Enable Enable<public>():void Enables this device.
Disable Disable<public>():void Disables this device.

Walkthrough

Let's build a "Dance Floor" scoring zone. We place a mutator zone over a stage. When a player steps onto the floor we greet them. While they're on the floor, every time they emote they bank a point; if they stop emoting we just note it. We also track who is currently on the floor.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

# A localized message helper — `message` params need localized text, not raw strings.
DanceMsg<localizes>(S:string):message = "{S}"

dance_floor := class(creative_device):

    # The placed mutator zone covering the stage. Assign it in the Details panel.
    @editable
    DanceZone : mutator_zone_device = mutator_zone_device{}

    # A HUD/text device or scoreboard could go here; we keep score in code.
    var Scores : [agent]int = map{}

    OnBegin<override>()<suspends>:void =
        # React when someone steps onto the dance floor.
        DanceZone.AgentEntersEvent.Subscribe(OnEnter)
        DanceZone.AgentExitsEvent.Subscribe(OnExit)
        # React to emotes happening inside the zone.
        DanceZone.AgentBeginsEmotingEvent.Subscribe(OnEmoteStart)
        DanceZone.AgentEndsEmotingEvent.Subscribe(OnEmoteEnd)

    # AgentEntersEvent hands us the agent directly (listenable(agent), not ?agent).
    OnEnter(Agent : agent):void =
        Print("A player stepped onto the dance floor!")
        if (not Scores[Agent]):
            set Scores[Agent] = 0

    OnExit(Agent : agent):void =
        Print("A player left the dance floor.")

    OnEmoteStart(Agent : agent):void =
        # Bank a point for emoting on the floor.
        var Current : int = 0
        if (Existing := Scores[Agent]):
            set Current = Existing
        set Current += 1
        if (set Scores[Agent] = Current) {}
        Print("Dance point! Total: {Current}")

    OnEmoteEnd(Agent : agent):void =
        Print("Player stopped dancing.")

Line by line:

  • DanceMsg<localizes>(S:string):message — a helper so any message-typed parameter (HUD text, etc.) can be built from a string. There is no StringToMessage.
  • @editable DanceZone : mutator_zone_device — you MUST declare the placed device as an editable field, then drag your placed zone onto it in the Details panel. Calling a method on a bare type would fail with Unknown identifier.
  • var Scores : [agent]int = map{} — a per-player score table.
  • In OnBegin we Subscribe a handler method to each of the four events. Handlers are methods at class scope.
  • OnEnter(Agent : agent)AgentEntersEvent is listenable(agent) (not ?agent), so the agent arrives unwrapped and ready to use. We initialize their score.
  • OnEmoteStart reads the current score with if (Existing := Scores[Agent]), increments it, and writes it back. The if (set Scores[Agent] = Current) {} form commits the map update (it decides, so we wrap it).
  • Note: emote events will NOT fire for players on the zone's Safe Team, or if Affects Players is disabled in the Details panel.

Common patterns

Sealed spawn room — Enable / Disable + GetAgentsInVolume

Keep a no-weapon mutator zone enabled during warmup, then disable it when the match begins so players can fight. We also count who's inside.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

spawn_room := class(creative_device):

    @editable
    SafeZone : mutator_zone_device = mutator_zone_device{}

    @editable
    StartButton : button_device = button_device{}

    OnBegin<override>()<suspends>:void =
        # Zone enforces its rules while enabled (set in Details: no weapons, no build).
        SafeZone.Enable()
        StartButton.InteractedWithEvent.Subscribe(OnMatchStart)

    OnMatchStart(Agent : agent):void =
        # How many players are still in the safe room?
        Occupants := SafeZone.GetAgentsInVolume()
        Print("Players still in spawn: {Occupants.Length}")
        # Drop the protective rules so combat can begin.
        SafeZone.Disable()

Hazard check — IsInVolume on a tick

Use IsInVolume to test whether a specific agent is inside the zone. Here a lava pit zone is polled and we report any player caught inside.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

lava_pit := class(creative_device):

    @editable
    LavaZone : mutator_zone_device = mutator_zone_device{}

    OnBegin<override>()<suspends>:void =
        loop:
            Sleep(1.0)
            CheckOccupants()

    CheckOccupants():void =
        for (Agent : LavaZone.GetAgentsInVolume()):
            # IsInVolume <decides> — use it inside an if to confirm.
            if (LavaZone.IsInVolume[Agent]):
                Print("A player is standing in the lava!")

Retarget the zone — UpdateSelectedTeam

When a player captures a control point, make the mutator zone's Selected Team match the capturer's team so the zone's rules now favor them.

using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }

control_point := class(creative_device):

    @editable
    PointZone : mutator_zone_device = mutator_zone_device{}

    OnBegin<override>()<suspends>:void =
        PointZone.AgentEntersEvent.Subscribe(OnCapture)

    OnCapture(Agent : agent):void =
        # Make the zone's Selected Team this agent's team.
        PointZone.UpdateSelectedTeam(Agent)
        # You could also retarget by class:
        PointZone.UpdateSelectedClass(Agent)
        Print("Zone retargeted to the capturing player.")

Gotchas

  • Enter/exit/emote events are listenable(agent), not listenable(?agent). Your handler receives (Agent : agent) already unwrapped — no if (A := Agent?) needed. (Contrast this with capture-area events like NeutralizeEvent which are listenable(?agent).)
  • Emote events are gated by Details-panel settings. AgentBeginsEmotingEvent and AgentEndsEmotingEvent will NOT fire if the agent is on the zone's Safe Team, or if Affects Players is disabled. If your dance scorer is silent, check those settings first.
  • IsInVolume is <decides>. It doesn't return a logic — call it inside an if (Zone.IsInVolume[Agent]): with square brackets, not parentheses.
  • GetAgentsInVolume() is a snapshot. It returns the agents in the zone at that instant. Re-query it each time you need fresh data rather than caching the array.
  • You must assign the placed device. Declaring @editable DanceZone : mutator_zone_device is only half the job — drag the actual placed Mutator Zone onto that field in the Details panel, or all your calls run against an empty default that does nothing.
  • Enable/Disable toggle the rule enforcement. A disabled zone stops applying its overrides AND stops firing its events, so don't disable a zone you still need to listen to.
  • message params need localized text. Any HUD/UI device you pair with the zone takes a message, not a string; build one with a <localizes> helper as shown — there is no StringToMessage.

Guides & scripts that use mutator_zone_device

Step-by-step tutorials that put this object to work.

Build your own lesson with mutator_zone_device

Generate a personalized, step-by-step lesson plan built around this object — grounded in this exact reference and our compile-verified knowledge base.

Build a lesson →