[Workaround] Spectate a player after calling Respawn()

As pointed out in many discussions on this forum:

The Verse “Agent.Respawn()” function is severely bugged and it will prevent many actions after a player’s been respawned using it.
I’ve been recently contacted by a creator which needed help because if a player’s been respawned using the Respawn() function, nobody can spectate him.

Instead of charging him for something Epic hasn’t been able to solve yet, here’s a my workaround everybody can use.

Island Settings

  1. Set Respawn Type to “Wave”, this is not strictly needed but it may be useful if all players are supposed to spawn at the same time
  2. Set “Only Allow Respawn if Spawn Pads Found” as true
  3. Set Spawn Limit off since we’ll need infinite respawns
  4. Set Respawn Time to “1.0”, which is the minimum you can set
  5. Set Override Spawn Immunity Time as true, and Spawn Immunity Time to “0.0”

image
image

Spawn Pads

  1. Add one or more Spawn Pad for each team you’ll have in your game.
  2. If your gamemode is based on teams (like 2v2 for example) remember to add the right amount of pads for each team.
  3. Leave their settings as default, but change the Team Index

Creative Device (Verse)

instant_respawn_device := class(creative_device):
    @editable
    RespawnTrigger : trigger_device = trigger_device{}
    @editable
    PlayerSpawnDevices : []player_spawner_device = array{}

    <# Standard OnBegin event #>
    OnBegin<override>()<suspends>:void=
        # Exposing the "RespawnAll" event with a trigger device, replace this with your own method or just call it using Verse
        RespawnTrigger.TriggeredEvent.Subscribe(RespawnAll)

        Sleep(1.0)
        for(SpawnDev : PlayerSpawnDevices):
            SpawnDev.SpawnedEvent.Subscribe(AgentRespawned)
        # Disable all respawns (the function is including a 1 sec delay, so all the initial player are spawned correctly when the game starts)
        DisableRespawns()

    <# Used to subscribe the actual RespawnAll function, which is async #>
    RespawnAll<public>(MaybeAgent : ?agent):void=
        spawn{PostRespawnAll()}

    <# Respawn process #>
    PostRespawnAll<public>()<suspends>:void=
        Sleep(1.0)

        # Enable all the spawnpads
        for(SpawnDev : PlayerSpawnDevices):
            SpawnDev.Enable()

        # Check each player present in the game
        for(Player : GetPlayspace().GetPlayers(), not Player.GetFortCharacter[].IsActive[]):
            # Respawn the player somewhere, it's not important since it will get eliminated and respawned on an actual pad
            Player.Respawn(vector3{Z := 512.0}, rotation{})
            # Wait
            Sleep(0.01)
            # Eliminate the player's character once again, this will trigger the automatic respawn action on those pads we've just enabled
            if(PChar := Player.GetFortCharacter[]):
                PChar.SetVulnerability(true)
                Sleep(0.01)
                PChar.Damage(damage_args{Amount := 999999999.0, Instigator := option{PChar}, Source := option{PChar}})    

    <# Each time someone respawns, check if pads can be disabled #>
    AgentRespawned(Agent : agent):void=
        var bCanDisableSpawnPads : logic = true
        for(Player : GetPlayspace().GetPlayers(), not Player.GetFortCharacter[].IsActive[]):
            set bCanDisableSpawnPads = false

        if(bCanDisableSpawnPads?):
            DisableRespawns()
    
    <# Disable all pads #>
    DisableRespawns<public>():void=
        # Disable all the pads in use
        for(SpawnDev : PlayerSpawnDevices):
            SpawnDev.Disable()

After building the Verse code, add the device into your scene and make sure to all your Spawn Pads to its list.

Considerations

Elimination count

Since this process will force respawn by spawning and eliminating the player, you should consider this step if you have something like a ranking system, or an “Eliminated” tracker device, so make sure to remove 1 “Eliminated” count each time you use it.

Double elimination on screen

Looking at the result, it’s pretty obvious that the player’s being eliminated and then respawned. You can mask the process, for example, by adding a black screen while the function is doing its things.

Further improvements

This is the generic solution you might want to use, but there’s still room for improvements and adaptations depending on your project setup.

Result

Video

Contacts

If you’ve found this workaround useful, consider following me on 𝕏: @kliansenpai

1 Like

Nice one, thanks for sharing, I’m kinda using this method for respawning now but no way I could do a tutorial on it since it’s so random

Hope Epic goes by and understand how much of an hassle it is

Also, did you try your version in Public since the spawn immunity time gets overriden ?

1 Like

Does this fix the DBNO issue because I thought you had to switch class as well and eliminate on switch

1 Like

Yeah exactly! It’s crazy we have to invent such elaborate shenanigans to solve issues which have been present for almost a whole year…
The public version of the map will be available this weekend, so if any issue comes out I will update the guide accordingly, I didn’t know the spawn immunity time might have problems too :exploding_head:.

Also, the map using this solution doesn’t rely on the DBNO device, so I don’t really know if it might solve that issue too. Theoretically, it’s respawning the player using the pad, so it should reset the agent state, but I can’t confirm for now!

1 Like

I have a problem with this script, I don’t spawn in the player spawner and spawn in a random place did you know how can i fix this problem?

There was indeed an issue with the code, but it was related to the time needed for the pads to respawn all player. So instead of using a generic Sleep() function, I binded the respawn event of each pad to check if all players’ve been respawned. If so, the new code will disable each spawn.

If everything is setup correctly, your players should respawn on the pads. Did you setup the respawn location correctly in the Island Settings?

1 Like

yes, the settings are done well, but I don’t know why this is happening…