Normal - UEFN Verse - When multiple people have the same canvas applied to them it'll remove it off the first. Only one person at a time can have the canvas.

When I add a canvas to a player, it works fine; when I add that same canvas to another player while the first one still has it, it’ll remove it from the first. I’m pretty sure this is an internal bug, but here is my code. I don’t even have any code that removes the widget, so I’m confused about how it could be removed.

OpenBalanceDisplay(Player:agent):void=
    UIHudElement_T1.Show(option {Player})
    if (PlayerUI := GetPlayerUI[player[Player]]):
        NewCanvas := BalanceDisplayCanvas()
        PlayerUI.AddWidget(NewCanvas, player_ui_slot{})
        if (set MyUIElement[player[Player]] = option{NewCanvas}):
            
BalanceDisplayCanvas():canvas=
    
    NewCanvas := canvas:
        Slots := array:
            canvas_slot:
                Anchors := anchors{ Maximum:= vector2{X:=1.0, Y:=1.0} }
                Offsets := margin{ Top:=75.0, Left:=100.0, Right:=100.0, Bottom := 100.0 }
                Widget := stack_box:
                    Orientation := orientation.Vertical
                    Slots := array:
                        stack_box_slot:
                            Widget := BalanceDisplay
    return NewCanvas

Are you using a map to set your canvas? For example:

var MaybeMyUIPerPlayer : [player]?canvas = map{}

Then your OpenBalanceDisplay would look more like this:

OpenBalanceDisplay(Agent:agent):void=
if (Player := player[Agent], PlayerUI := GetPlayerUI[Player]):
            if (MyUI := MaybeMyUIPerPlayer[Player]?):
                PlayerUI.RemoveWidget(MyUI)
                if (set MaybeMyUIPerPlayer[Player] = false) {}
            else:
                NewUI := BalanceDisplayCanvas()
                PlayerUI.AddWidget(NewUI, player_ui_slot{InputMode := ui_input_mode.None})
                if (set MaybeMyUIPerPlayer[Player] = option{NewUI}) {}
1 Like

I mean, that’s almost exactly what I did; I don’t ever need to remove the widget. I’ve copied and pasted that exactly, but I don’t know how this will differ from what I had before.

This did not fix my issue, two people still cannot have the same canvas at the same time. Once the second person is assigned it, it gets removed off the first.

1 Like

Also experiencing this, it seems players are sharing the same UI space, even when the players are assigned a canvas with a map.

I’m assuming that this is related.

Update: The buttons / text / whatever you use need to be defined inside the MakeCanvas() function because if they’re at the top of your script per the docs, they’re classed as global or shared and so they get “removed” as has been happening.

2 Likes

Here is an example of what AxelChapek is talking about.
image

1 Like

I am having this exact issue, has anyone found a solution? This seems like it would be a common function designers would implement.

I almost succeed to correct this problem. I had the same issue, when a second player log in it stole the UI from the last one who did it.

So I followed this tutorial :

Here’s my class code:

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

# See https://dev.epicgames.com/documentation/en-us/uefn/create-your-own-device-in-verse for how to create a verse device.

MakeGameUI<constructor><public>(InPlayer : agent) := game_ui:
    MaybePlayer := option{InPlayer}
    MaybePlayerUI := option{GetPlayerUI[player[InPlayer]]} 

# A Verse-authored creative device that can be placed in a level
game_ui := class():
    var MyCanvas<internal> : canvas = canvas{}
    LapsCountWidget<internal> : button_loud = button_loud{}

    MaybePlayer<internal> : ?agent = false
    MaybePlayerUI<internal> : ?player_ui = false

    ScoreManagerDevice<internal> : score_manager_device = score_manager_device{}
    
    LapsText<localizes>(NbLaps : int) : message = "Laps {NbLaps} of 10"
    LapsTextDefaut<localizes>() : message = "No Lap Started Yet !"
    var TotalLaps<private> : int = 0

    block: 
        set MyCanvas = canvas:
            Slots := array:
                canvas_slot:
                    Anchors := anchors{Minimum := vector2{X := 0.5, Y := 0.0}, Maximum := vector2{X := 0.5, Y := 0.0}}
                    Offsets := margin{Top := 100.0, Left := 0.0, Right := 0.0, Bottom := 0.0}
                    Alignment := vector2{X := 0.5, Y := 0.5}
                    SizeToContent := true
                    Widget := LapsCountWidget

    UpdateInitialUI<private>(): void =
        if (PlayerUI := MaybePlayerUI?):
            LapsCountWidget.SetText(LapsTextDefaut())

    UpdateUI<private>(): void =
        if (PlayerUI := MaybePlayerUI?):
            LapsCountWidget.SetText(LapsText(TotalLaps))

    AddGameUIToUI<public>() : void =
        if (PlayerUI := MaybePlayerUI?):
            PlayerUI.AddWidget(MyCanvas)
    
            UpdateInitialUI()

    UpdateLapCount<public>(Points : int) : void =
        set TotalLaps = Points
        UpdateUI()

In my other file that track the game I have this code:

OnPlayerSpawn(InPlayer : agent) : void=
        #Print("A player just spawned!")
        if(PlayerLap := TotalOfLaps[InPlayer], Player := player[InPlayer]):

        else if (Player := player[InPlayer]):    
            set GameUI = MakeGameUI(InPlayer)
                  
            if(set TotalOfLaps[Player] = 0):
                GameUI.AddGameUIToUI()  

    HandleCheckpointCompleted(Agent:agent):void=
        if (Player := player[Agent], LapOfPlayer = TotalOfLaps[Player]):
            set LapOfPlayer = LapOfPlayer + 1
        if (Player := player[Agent], set TotalOfLaps[Player] = LapOfPlayer):
            GameUI.UpdateLapCount(LapOfPlayer)

With this code, every player have the custom UI, the only problem that it update only the one of the last player that Has spawn.

When I succeed to correct this problem, I’ll post the final result

I successfully made a functionnal custom ui for multiple player, but I had to do a Work Around, because the system seem to lost the Focus of the first Created UI and Event when trying to delete the older UI don’t seem to work, so I had to recreate a second, third, fourth… UI in front of the older to made it work for multiplayer. Here is the Final code:

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

MakeGameUI<constructor><public>(InPlayer : agent) := game_ui:
    MaybePlayer := option{InPlayer}
    MaybePlayerUI := option{GetPlayerUI[player[InPlayer]]} 

game_ui := class():
    var MyCanvas<internal> : canvas = canvas{}
    LapsCountWidget<internal> : button_loud = button_loud{}

    MaybePlayer<internal> : ?agent = false
    MaybePlayerUI<internal> : ?player_ui = false
    
    LapsText<localizes>(NbLaps : int) : message = "Laps {NbLaps} of 10"
    LapsTextDefaut<localizes>() : message = "No Lap !"
    var TotalLaps<private> : int = 0

    block: 
        set MyCanvas = canvas:
            Slots := array:
                canvas_slot:
                    Anchors := anchors{Minimum := vector2{X := 0.5, Y := 0.0}, Maximum := vector2{X := 0.5, Y := 0.0}}
                    Offsets := margin{Top := 100.0, Left := 0.0, Right := 0.0, Bottom := 0.0}
                    Alignment := vector2{X := 0.5, Y := 0.5}
                    SizeToContent := true
                    Widget := LapsCountWidget

    UpdateInitialUI<private>(): void =
        if (PlayerUI := MaybePlayerUI?):
            LapsCountWidget.SetText(LapsTextDefaut())

    UpdateUI<private>(): void =
        if (PlayerUI := MaybePlayerUI?):
            LapsCountWidget.SetText(LapsText(TotalLaps))

    RemoveAddGameUIToUI<public>() : void =
        Print("Just before add UI")
        if (PlayerUI := MaybePlayerUI?):
            Print("Adding UI")
            PlayerUI.AddWidget(MyCanvas)
            Print("Initial Message")
            UpdateInitialUI()

    RefreshGameUI<public>(Points : int): void =
        Print("Just before refresh UI")
        if (PlayerUI := MaybePlayerUI?):
            Print("Adding UI")
            PlayerUI.AddWidget(MyCanvas)
            Print("Set Total Points")
            set TotalLaps = Points
            Print("Number of Points: {Points}")
            UpdateUI()