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

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