UI Material block causes lag spikes when loaded into a UI

Summary

In the latest update (36.20), loading a material block UI with a linked value (e.g, Progress:= 1.0) causes a lag spike lasting several seconds. This issue is particularly problematic on lower-performing consoles.

Please select what you are reporting on:

Unreal Editor for Fortnite

What Type of Bug are you experiencing?

Verse

Steps to Reproduce

Create a Verse script that displays a UI to the player.
In the UI, include a Material Block widget.
Set a material parameter (e.g., Progress := 0.5) linked to the material block.
Link the opening UI to a mutator zone or a button

Expected Result

The UI you should with no lag spikes/freezes

Observed Result

Run the script and observe the lag spike when the UI is shown.

Platform(s)

PC

Hey is there any update to the case?

FORT-943376 changed to ‘Needs More Info’. We’re missing information that would help us determine the source of the issue.

Hi @Stug, could you provide media and your code setup to help us reproduce this issue?

Feel free to private message me if you’d prefer

1 Like

Hey sure thing here is what you asked. I’ve attached a small part of the code, where it initiates the material block values. Once that attached to a canvas UI that displays those material blocks.

The lag spilkes also affect EVERYONE in the session so that is even more gamebreaking. It happens mostly when a player opens for the first time a UI with material block values.

Media video link: Watch 2025-08-08 23-21-16 | Streamable

Phone := class():
    var CapPrestige: int = 0
    var MainCanvas : canvas = canvas{}
    var PhoneImage : texture = UpgradePerk
    var UpgradeButton1 : button_regular = button_regular{}
    var UpgradeButton2 : button_regular = button_regular{}
    var UpgradeButton3 : button_regular = button_regular{}
    var UpgradeButton4 : button_regular = button_regular{}
    var UpgradeButton5 : button_regular = button_regular{}

    MyMaterial:PlayerInfoUI.ProgressBar_material=PlayerInfoUI.ProgressBar_material{Progress:=0.0}
    MyMaterial2:PlayerInfoUI.ProgressBar_material=PlayerInfoUI.ProgressBar_material{Progress:=0.0}
    MyMaterial3:PlayerInfoUI.ProgressBar_material=PlayerInfoUI.ProgressBar_material{Progress:=0.0}
    MyMaterial4:PlayerInfoUI.ProgressBar_material=PlayerInfoUI.ProgressBar_material{Progress:=0.0}
    MyMaterial5:PlayerInfoUI.ProgressBar_material=PlayerInfoUI.ProgressBar_material{Progress:=0.0}

    TextUpgrade1 : text_block = text_block {DefaultTextColor := MakeColorFromHex("#00FFC6FF"),DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=Black}
    TextCurrentStat1 : text_block = text_block {DefaultTextColor := MakeColorFromHex("#ffffff"),DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=Black}
    TextCurrentStat2 : text_block = text_block {DefaultTextColor := MakeColorFromHex("#ffffff"),DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=Black}
    TextCurrentStat3 : text_block = text_block {DefaultTextColor := MakeColorFromHex("#ffffff"),DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=Black}
    TextCurrentStatDamage : text_block = text_block {DefaultTextColor := MakeColorFromHex("#ffffff"),DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=Black}
    TextUpgradeDamage : text_block = text_block {DefaultTextColor := MakeColorFromHex("#00FFC6FF"),DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=Black}
    TextCurrentStatBoss : text_block = text_block {DefaultTextColor := MakeColorFromHex("#ffffff"),DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=Black}
    TextUpgradeBoss : text_block = text_block {DefaultTextColor := MakeColorFromHex("#00FFC6FF"),DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=Black}
    TextLevel : text_block = text_block {DefaultTextColor := MakeColorFromHex("#000000FF")}
    TextLevel2 : text_block = text_block {DefaultTextColor := MakeColorFromHex("#000000FF")}
    TextLevel3 : text_block = text_block {DefaultTextColor := MakeColorFromHex("#000000FF")} 
    TextLevel4 : text_block = text_block {DefaultTextColor := MakeColorFromHex("#000000FF")}
    TextLevel5 : text_block = text_block {DefaultTextColor := MakeColorFromHex("#000000FF")} #White= ffffff
    TextCash : text_block = text_block {DefaultTextColor := MakeColorFromHex("#00FF01FF"),DefaultShadowOffset:=option{vector2{X:=2.5,Y:=2.5}},DefaultShadowColor:=MakeColorFromHex("#000B00FF")}

    var Currency: CurrencyManager = CurrencyManager{}
    var HUDDevice: hud_message_device = hud_message_device{}
    var DamageUp: damage_amplifier_powerup_device = damage_amplifier_powerup_device{}
    var HUDNotEnough: hud_message_device = hud_message_device{}
    var SoundBuy: audio_player_device = audio_player_device{}
    var Cam: gameplay_camera_fixed_point_device = gameplay_camera_fixed_point_device{}

    var ExitButton : button_quiet = button_quiet{}

    var Sounds: []audio_player_device = array{}

    ToMessage<localizes>(String : string) : message = "{String}"


    SetFloat(Number : float): string=
        # Handle numbers less than 1,000
        if (Number < 10000.0) {
            Thousands := Number / 1.0
            if (ThousandsToInt := Int[Thousands]) {
                if (ThousandsToInt * 1.0 = Thousands) {
                    return "{ThousandsToInt}.0"
                }
                else {
                    Remainder := Number - (ThousandsToInt * 1.0)
                    DecimalPart := Remainder / 0.1
                    if (Decimal := Int[DecimalPart]) {
                        return "{ThousandsToInt}.{Decimal}"
                    }
                }
            }
        }

        return ""

    ConvertToText(Number : float): string=
        # Handle numbers less than 1,000
        if (Number < 1000.0) {
            if (NumberInt := Int[Number]) {
                return "{NumberInt}"
            }
            return ""
        }
        # Handle numbers between 1,000 and 10,000
        else if (Number < 10000.0) {
            Thousands := Number / 1000.0
            if (ThousandsToInt := Int[Thousands]) {
                if (ThousandsToInt * 1.0 = Thousands) {
                    return "{ThousandsToInt}.0K"
                }
                else {
                    Remainder := Number - (ThousandsToInt * 1000.0)
                    DecimalPart := Remainder / 100.0
                    if (Decimal := Int[DecimalPart]) {
                        return "{ThousandsToInt}.{Decimal}K"
                    }
                }
            }
        }
        # Handle numbers between 10,000 and 100,000
        else if (Number < 100000.0) {
            TensOfThousands := Number / 1000.0
            if (TensOfThousandsToInt := Int[TensOfThousands]) {
                if (TensOfThousandsToInt * 1.0 = TensOfThousands) {
                    return "{TensOfThousandsToInt}.0K"
                }
                else {
                    Remainder := Number - (TensOfThousandsToInt * 1000.0)
                    DecimalPart := Remainder / 100.0
                    if (Decimal := Int[DecimalPart]) {
                        return "{TensOfThousandsToInt}.{Decimal}K"
                    }
                }
            }
        }
        # Handle numbers between 100,000 and 1,000,000
        else if (Number < 1000000.0) {
            HundredsOfThousands := Number / 1000.0
            if (HundredsOfThousandsToInt := Int[HundredsOfThousands]) {
                if (HundredsOfThousandsToInt * 1.0 = HundredsOfThousands) {
                    return "{HundredsOfThousandsToInt}.0K"
                }
                else {
                    Remainder := Number - (HundredsOfThousandsToInt * 1000.0)
                    DecimalPart := Remainder / 10000.0
                    if (Decimal := Int[DecimalPart]) {
                        return "{HundredsOfThousandsToInt}.{Decimal}K"
                    }
                }
            }
        }
        # Handle numbers between 1,000,000 and 1,000,000,000
        else if (Number < 1000000000.0) {
            Millions := Number / 1000000.0
            if (MillionsToInt := Int[Millions]) {
                if (MillionsToInt * 1.0 = Millions) {
                    return "{MillionsToInt}.0M"
                } else {
                    Remainder := Number - (MillionsToInt * 1000000.0)
                    DecimalPart := Remainder / 100000.0
                    if (Decimal := Int[DecimalPart]) {
                        return "{MillionsToInt}.{Decimal}M"
                    }
                }
            }
        }
        # Handle numbers 1,000,000,000 and above
        else {
            Billions := Number / 1000000000.0
            if (BillionsToInt := Int[Billions]) {
                if (BillionsToInt * 1.0 = Billions) {
                    return "{BillionsToInt}.0B"
                } else {
                    Remainder := Number - (BillionsToInt * 1000000000.0)
                    DecimalPart := Remainder / 100000000.0
                    if (Decimal := Int[DecimalPart]) {
                        return "{BillionsToInt}.{Decimal}B"
                    }
                }
            }
        }

        return ""
    
    AddUI(Agent : agent)<suspends> : void=
        spawn{HandlePersonalProgression(Agent)}
        HUDDevice.Show(Agent)
        if(Player := player[Agent], PlayerUI := GetPlayerUI[Player]):
            set MainCanvas = CreateUI()
            PlayerUI.AddWidget(MainCanvas , player_ui_slot{InputMode := ui_input_mode.All})

    HandlePersonalProgression(Agent: agent)<suspends>:void=
        if (PlayerObj := player[Agent],AgentData := Currency.AgentMap[PlayerObj]):
            if(AgentData.Rebirth<=4):
                set CapPrestige = AgentData.Rebirth
            else if(AgentData.Rebirth>4):
                set CapPrestige = 4
            # = Player Data =
            if:
                Char:fort_character = Agent.GetFortCharacter[]
                Char.SetMaxHealth(AgentData.MaxHealth)
                Char.SetMaxShield(AgentData.MaxShield)
            DamageUp.SetMagnitude(AgentData.DamageBuff)
            DamageUp.Pickup(Agent)
            #Material Setup
            set MyMaterial.Progress=(1.0*AgentData.GoldUpgradeCount / 100.0)* 100.0
            if (MyMaterial.Progress > 100.0):
                set MyMaterial.Progress = 100.0
            set MyMaterial2.Progress=(1.0*AgentData.HealthUpgradeCount / 100.0)* 100.0
            if (MyMaterial2.Progress > 100.0):
                set MyMaterial2.Progress = 100.0
            set MyMaterial3.Progress=(1.0*AgentData.ShieldUpgradeCount / 100.0)* 100.0
            if (MyMaterial3.Progress > 100.0):
                set MyMaterial3.Progress = 100.0
            set MyMaterial4.Progress=(1.0*AgentData.DamageUpgradeCount / 40.0)* 100.0
            if (MyMaterial4.Progress > 100.0):
                set MyMaterial4.Progress = 100.0
            set MyMaterial5.Progress=(1.0*AgentData.GoldBoss / 50.0)* 100.0
            if (MyMaterial5.Progress > 100.0):
                set MyMaterial5.Progress = 100.0
1 Like

Hey is there any updates on this issue? Thanks

1 Like

hey! did you find a solution for this? ive heard that instancing the materials and saving them so u can reopen them could fix it. Didnt work for us though.

Hey, nope didn’t work for us neither and seemed that this issue will still not be fixed :frowning:

Hey Vath! Is there any updates on this matter? I haven’t heard updates on it. Thanks!

Hey Stug. Updates are occurring on this thread as it looks like the same issue. It’s currently assigned to an Engineer for investigation

Ticket is FORT-947513