How to detect if a player stops moving?

I would like to check if a player has stopped moving after entering a Mutator Zone.

How could I achieve this in Verse? Or is there a simpler solution with devices?

My current idea is to get the player transform and compare it to the previous once inside a loop, but I can’t figure out how to write that. Any help very much appreciated!

Hey Fub, I don’t know of a way to do this with devices and I suspect there might not be one. Doing it with Verse using the method you mentioned does seem to work, but a few things make it quite involved, including:

  • Handling players leaving the zone before standing still
  • Handling players joining and leaving matches
  • Accounting for elapsed time
  • Ensuring players are only iterated once and calculations aren’t doubled up

I felt like a break from my project so I put together a script for it. It could be a useful as a general example so I’ve made it a snippet here.

Once you have player_standstill_tracker from the snippet, you will be able to detect players entering the zone and standing still like so:

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

player_tracker_device := class(creative_device):

    @editable
    MovementZone: mutator_zone_device = mutator_zone_device{}

    @editable
    StandstillTrackingDevice: standstill_tracking_device = standstill_tracking_device{}


    OnBegin<override>()<suspends>: void =

        # Subscribe to mutator_zone_device events
        MovementZone.AgentEntersEvent.Subscribe(HandleAgentEntersMovementZone)
        

    HandleAgentEntersMovementZone(Agent: agent): void =

        spawn. AwaitAgentStandStillOrExitZone(Agent)


    AwaitAgentStandStillOrExitZone(Agent: agent)<suspends>: void =

        if. StandstillTrackingData := StandstillTrackingDevice.GetAgentTrackingData[Agent]
        then:
            race:
                # The player leaves the zone before standing still
                AwaitAgentExitsZone(Agent)

                # The player stands still
                StandstillTrackingData.StandStillEvent.Await()

            # If the player is standing still here, we know it's inside the zone
            if. StandstillTrackingData.IsStandingStill[]
            then. Print("We are at our destination 🎉")
            else. Print("Left zone without standing still ")


    AwaitAgentExitsZone(Agent: agent)<suspends>: void =

        # Await exit events until agent matches
        loop:
            LeavingAgent := MovementZone.AgentExitsEvent.Await()
            if. LeavingAgent = Agent then. break
2 Likes

Thanks for such a generous response Rift, I appreciate it.

I had only made it so far as using ‘spawn’ to get my loop running. This setup works but I hadn’t even considered the challenge of other players joining/leaving the match.

player_tracker_device := class(creative_device):

    @editable
    MovementZone : mutator_zone_device = mutator_zone_device{}

    @editable
    Teleporter : teleporter_device  = teleporter_device{}

    # Runs when the device is started in a running game
    OnBegin<override>()<suspends>:void =
        
        MovementZone.AgentEntersEvent.Subscribe(HandleAgentEntersMovementZone)


    GetTransformPerTick<private>(FortCharacter:fort_character)<suspends>:void = 

        loop:
            OldPosition : vector3 = FortCharacter.GetTransform().Translation
            Sleep(1.0)
            NewPosition : vector3 = FortCharacter.GetTransform().Translation
            if(IsAlmostEqual[OldPosition, NewPosition, 0.0]):
                if(Agent := FortCharacter.GetAgent[]):
                    Teleporter.Teleport(Agent)
                    break
            else:
                Print("Player is still moving!")
                
    HandleAgentEntersMovementZone<private>(Agent:agent):void =

        if(FortCharacter := Agent.GetFortCharacter[]):
            spawn {GetTransformPerTick(FortCharacter)}

I have a formatting question. You use periods in ways I don’t recognize, for example:

        if. StandstillTrackingData := StandstillTrackingDevice.GetAgentTrackingData[Agent]
        do. set NewMap = ConcatenateMaps(NewMap, map{Key => Value})

Is this just another way of doing ()?

Yea, the player leaving the zone before standing still is another thing to think about. In your example I believe it would continue to loop after the player exits the mutator zone volume.

The periods I use are another syntax option instead of parenthesis, yea. I’ve started to prefer it because I find it easier manage multi-line expressions that way. e.g.

        Foo: []int = array{}

        # Colon = multiline block
        for(Bar : Foo):
            Print("1")
            Print("2")

        # Period = single line block
        for(Bar : Foo). Print("1")

        # Period single line for expression, colon multiline for loop block
        for. Bar : Foo
        do:
            Print("1")
            Print("2")

        # Period multi line for expression, period single line for loop block
        for:
            Bar : Foo
            true = true
        do. Print("1")
1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.