Problems with spectator mode on my map

So i have a problem with my spectator mode, if player re-enters spectator mode second time right after leaving it or changing class, it bugs out and doesn`t show mouse and i cant do anything. I tried setting the InputMode to All, but then the default previous/next player buttons dont show up. How could i fix this problem?

using { /Fortnite.com/Devices }

using { /Verse.org/Simulation }

using { /UnrealEngine.com/Temporary/Diagnostics }

using { /Fortnite.com/Characters }

using { /UnrealEngine.com/Temporary/UI }

using { /Fortnite.com/UI }

using { /UnrealEngine.com/Temporary/SpatialMath }

using { /Fortnite.com/FortPlayerUtilities }

using { /Fortnite.com/Playspaces }

using { /Fortnite.com/Game }

using { /Verse.org/Random }

# A Verse-authored creative device that can be placed in a level

spectator_mode_device := class(creative_device):

@editable SpectateButton:button_device = button_device{}

@editable SpectatorClass:class_and_team_selector_device = class_and_team_selector_device{}

@editable RespawnQueueOnClass:class_and_team_selector_device = class_and_team_selector_device{}

@editable RespawnQueueOffClass:class_and_team_selector_device = class_and_team_selector_device{}

@editable DeathMutatorZone:mutator_zone_device = mutator_zone_device{}

@editable PlayerSpawners : \[\]player_spawner_device = array{}

@editable PlayerQueueSwitch : switch_device = switch_device{}



var EachPlayerUI : \[player\]?canvas = map{}

RespawnText<localizes> : message = "HUB"

ButtonRespawn : button_loud = button_loud{}

\# Runs when the device is started in a running game

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

    SpectateButton.InteractedWithEvent.Subscribe(GoToSpectator)

    DeathMutatorZone.AgentEntersEvent.Subscribe(OnPlayerEnteredZone)



GoToSpectator(Agent:agent):void=

    if(Player := player\[Agent\], PlayerUI := GetPlayerUI\[Player\]):

        if(FortChar := Player.GetFortCharacter\[\], Playspace := GetPlayspace()):

            \# Remove any existing UI for this player to prevent stacking

            if (ExistingUI := EachPlayerUI\[Player\]?):

                PlayerUI.RemoveWidget(ExistingUI)

                if (set EachPlayerUI\[Player\] = false) {}

            SpectatorClass.ChangeTeamAndClass(Agent)

            FortChar.Damage(300.0)

            SetPlayerUI(Player, PlayerUI)



\# Handle player elimination and switch to spectator mode

OnPlayerEnteredZone(Agent:agent):void=

    GoToSpectator(Agent)



SetPlayerUI(Player: player, PlayerUI : player_ui):void=

    NewUI:=CreateMyUI()

    PlayerUI.AddWidget(NewUI)

    if(set EachPlayerUI\[Player\] = option{NewUI}):

OnRespawnClicked(WidgetPlayer:widget_message):void=

    if(Player:= WidgetPlayer.Player, PlayerUI:= GetPlayerUI\[Player\], Agent:= agent\[Player\]):

        if(UIPlayerExisting:= EachPlayerUI\[Player\]?):

            if (PlayerQueueSwitch.GetCurrentState\[Agent\]):

                RespawnQueueOnClass.ChangeTeamAndClass(Agent)

            else:

                RespawnQueueOffClass.ChangeTeamAndClass(Agent)

            PlayerUI.RemoveWidget(UIPlayerExisting)

            RandomIndex := GetRandomInt(0, PlayerSpawners.Length - 1)

            if (SelectedSpawner := PlayerSpawners\[RandomIndex\]):

                \# Get the transform from the selected spawner

                SpawnerTransform := SelectedSpawner.GetTransform()

                \# Use the spawner's location and rotation for respawn

                Player.Respawn(SpawnerTransform.Translation, SpawnerTransform.Rotation)

            if(set EachPlayerUI\[Player\] = false):

CreateMyUI() : canvas =

    ButtonRespawn.SetText(RespawnText)

    ButtonRespawn.OnClick().Subscribe(OnRespawnClicked)

    MyCanvas : canvas = canvas:

        Slots := array:

            canvas_slot:

                Anchors := anchors{Minimum := vector2{X := 0.5, Y := 0.95}, Maximum := vector2{X := 0.5, Y := 0.95}}

                Offsets := margin{Top := 0.0, Left := 5.0, Right := 5.0, Bottom := 0.0}

                Alignment := vector2{X := 0.5, Y := 0.5}

                SizeToContent := true

                Widget := ButtonRespawn

    return MyCanvas

Hey @yyyuma how are you?

I’ve been changing some parts of your code and it seems to work better. Let me show you!

  1. I added a variable to store the Canvas:
    # Canvas container for the UI elements
    var MyCanvas : canvas = canvas{} # New
  1. I changed the “CreateMyUI” to avoid conflicts with that new variable:
    CreateMyUI() : canvas =
        ButtonRespawn.SetText(RespawnText)
        ButtonRespawn.OnClick().Subscribe(OnRespawnClicked)

        MainCanvas : canvas = canvas: # New name
            Slots := array:
                canvas_slot:
                    Anchors := anchors{Minimum := vector2{X := 0.5, Y := 0.95}, Maximum := vector2{X := 0.5, Y := 0.95}}
                    Offsets := margin{Top := 0.0, Left := 5.0, Right := 5.0, Bottom := 0.0}
                    Alignment := vector2{X := 0.5, Y := 0.5}
                    SizeToContent := true
                    Widget := ButtonRespawn
        return MainCanvas # Changed for the new name
  1. Then, I changed the “SetPlayerUI” function this way:
    SetPlayerUI(Player: player):void= # Removed the PlayerUI input data
        if(PlayerUI := GetPlayerUI[Player]):
            set MyCanvas = CreateMyUI() #new
            #NewUI:=CreateMyUI()
            #PlayerUI.AddWidget(NewUI)
            #if(set EachPlayerUI[Player] = option{NewUI}):
            PlayerUI.AddWidget(MyCanvas , player_ui_slot{InputMode := ui_input_mode.All})
  1. and the last thing I did is polishing the “OnRespawnClicked” function:
    OnRespawnClicked(WidgetPlayer:widget_message):void=
        if(Player:= WidgetPlayer.Player, PlayerUI:= GetPlayerUI[Player], Agent:= agent[Player]):
            # if(UIPlayerExisting:= EachPlayerUI[Player]?): # you don't need to check this
                if (PlayerQueueSwitch.GetCurrentState[Agent]):
                    RespawnQueueOnClass.ChangeTeamAndClass(Agent)
                else:
                    RespawnQueueOffClass.ChangeTeamAndClass(Agent)

                PlayerUI.RemoveWidget(MyCanvas)
                RandomIndex := GetRandomInt(0, PlayerSpawners.Length - 1)
                if (SelectedSpawner := PlayerSpawners[RandomIndex]):
                    # Get the transform from the selected spawner
                    SpawnerTransform := SelectedSpawner.GetTransform()
                    # Get the spawner's position and Add height offset to spawn above ground level
                    SpawnLocation := SpawnerTransform.Translation + vector3{X := 0.0, Y := 0.0, Z := 120.0} # New
                    # Use the spawner's location and rotation for respawn
                    Player.Respawn(SpawnLocation, SpawnerTransform.Rotation)

                if(set EachPlayerUI[Player] = false):

These changes worked fine for me. Please test it and let me know if you need more help!