關於 Puerts 的效能問題

当麻發表於2024-07-06

Puerts 在 UE 開發中提供了一定的便利性,可以用程式碼的方式寫藍圖,但是官方是不推薦這麼做的

原話如下

那麼這個效能問題究竟有多大呢

這裡先用 C++ 寫一個測試程式碼

#include "TestWidget.h"

#include "Blueprint/WidgetBlueprintLibrary.h"
#include "Blueprint/WidgetLayoutLibrary.h"

int32 UTestWidget::NativePaint(const FPaintArgs& Args, const FGeometry& AllottedGeometry,
                               const FSlateRect& MyCullingRect, FSlateWindowElementList& OutDrawElements, int32 LayerId,
                               const FWidgetStyle& InWidgetStyle, bool bParentEnabled) const
{
    FPaintContext Context(AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle, bParentEnabled);

    FVector2D ViewportSize = UWidgetLayoutLibrary::GetViewportSize(const_cast<UTestWidget*>(this));

    FVector2D LeftTopPoint = FVector2D(ViewportSize.X * 0.2, ViewportSize.Y * 0.2);
    FVector2D RightTopPoint = FVector2D(ViewportSize.X * 0.8, ViewportSize.Y * 0.2);
    FVector2D LeftBottomPoint = FVector2D(ViewportSize.X * 0.2, ViewportSize.Y * 0.8);
    FVector2D RightBottomPoint = FVector2D(ViewportSize.X * 0.8, ViewportSize.Y * 0.8);

    UWidgetBlueprintLibrary::DrawLine(Context, LeftTopPoint, RightTopPoint);
    UWidgetBlueprintLibrary::DrawLine(Context, RightTopPoint, RightBottomPoint);
    UWidgetBlueprintLibrary::DrawLine(Context, RightBottomPoint, LeftBottomPoint);
    UWidgetBlueprintLibrary::DrawLine(Context, LeftBottomPoint, LeftTopPoint);

    return Super::NativePaint(Args, AllottedGeometry, MyCullingRect, OutDrawElements, LayerId, InWidgetStyle,
                              bParentEnabled);
}

然後用 Unreal Insight 看一下效能資料

只看 Paint 的資料,作為對照組

然後在 TypeScript 實現一樣的程式碼

import { $Ref } from "puerts"
import * as UE from "ue"

class TS_TestWidget extends UE.PuertsWidget
{
    OnPaint(Context: $Ref<UE.PaintContext>): void 
    {
        let ViewportSize = UE.WidgetLayoutLibrary.GetViewportSize(this);

        let LeftTopPoint = new UE.Vector2D(ViewportSize.X * 0.2, ViewportSize.Y * 0.2);
        let RightTopPoint = new UE.Vector2D(ViewportSize.X * 0.8, ViewportSize.Y * 0.2);
        let LeftBottomPoint = new UE.Vector2D(ViewportSize.X * 0.2, ViewportSize.Y * 0.8);
        let RightBottomPoint = new UE.Vector2D(ViewportSize.X * 0.8, ViewportSize.Y * 0.8);

        UE.WidgetBlueprintLibrary.DrawLine(Context, LeftTopPoint, RightTopPoint);
        UE.WidgetBlueprintLibrary.DrawLine(Context, RightTopPoint, RightBottomPoint);
        UE.WidgetBlueprintLibrary.DrawLine(Context, RightBottomPoint, LeftBottomPoint);
        UE.WidgetBlueprintLibrary.DrawLine(Context, LeftBottomPoint, LeftTopPoint);
    }
}
export default TS_TestWidget

跟 C++ 對比,在最慢的時候可以可以達到幾十倍的差距,假如有幾十個這樣的 Widget 同時執行(例如血條),那麼肯定是會出現遊戲頓卡或者遊戲幀數低的情況

所以在 Puerts 中儘量不寫每幀都會執行的邏輯,避免因為跨語言呼叫而造成的效能問題

相關文章