If SetAlignmentInViewport is called in the UMG Construct, it is ignored internally. This is due to a change that came in 5.1, so it worked fine in 5.0.
First, when the Set Alignment in Viewport node is called with Construct, it goes through the first half of the code below
void UUserWidget::SetAlignmentInViewport(FVector2D Alignment) { if (UGameViewportSubsystem* Subsystem = UGameViewportSubsystem::Get(GetWorld())) { if (bIsManagedByGameViewportSubsystem) { FGameViewportWidgetSlot ViewportSlot = Subsystem->GetWidgetSlot(this); if (ViewportSlot.Alignment != Alignment) { ViewportSlot.Alignment = Alignment; Subsystem->SetWidgetSlot(this, ViewportSlot); } } else { FGameViewportWidgetSlot ViewportSlot; ViewportSlot.Alignment = Alignment; Subsystem->SetWidgetSlot(this, ViewportSlot); } } }
Then, in the code below, it tries to set Alighment for the Slot managed by Subsystem, but at the time of Construct, SlotInfo.FullScreenWidget is null, so nothing is actually set. FullScreenWidget is null at the time of Construct, so the process ends without actually setting anything.
void UGameViewportSubsystem::SetWidgetSlot(UWidget* Widget, FGameViewportWidgetSlot Slot) { if (Widget && !Widget->HasAnyFlags(RF_BeginDestroyed)) { TWeakObjectPtr<UWidget> TempObject = const_cast<UWidget*>(Widget); FSlotInfo& SlotInfo = ViewportWidgets.FindOrAdd(TempObject); Widget->bIsManagedByGameViewportSubsystem = true; SlotInfo.Slot = Slot; if (TSharedPtr<SConstraintCanvas> WidgetHost = SlotInfo.FullScreenWidget.Pin()) { check(SlotInfo.FullScreenWidgetSlot); TPair<FMargin, bool> OffsetArgument = UE::UMG::Private::CalculateOffsetArgument(Slot); SlotInfo.FullScreenWidgetSlot->SetOffset(OffsetArgument.Get<0>()); SlotInfo.FullScreenWidgetSlot->SetAutoSize(OffsetArgument.Get<1>()); SlotInfo.FullScreenWidgetSlot->SetAnchors(Slot.Anchors); SlotInfo.FullScreenWidgetSlot->SetAlignment(Slot.Alignment); WidgetHost->Invalidate(EInvalidateWidgetReason::Layout); //todo set the zorder } } }
FullScreenWidget is set at the timing of AddtoViewport of Construct. Specifically, the settings are made in the following code. The problem occurs because the Alighment is not set, but the default value is entered.
void UGameViewportSubsystem::AddToScreen(UWidget* Widget, ULocalPlayer* Player, FGameViewportWidgetSlot& Slot) { ... SlotInfo.Slot = Slot; SlotInfo.LocalPlayer = Player; SlotInfo.FullScreenWidget = FullScreenCanvas; SlotInfo.FullScreenWidgetSlot = RawSlot;
In addition, because ViewportWidgets in the SetWidgetSlot function contains elements at the time of Construct, ViewportWidgets.FindOrAdd works with Find instead of Add. Therefore, the Alighment set in SetAlignmentInViewport is passed to SetWidgetSlot, but this is not working either.
To work around this issue without modifying the engine code, you need to call Set Alignment in Viewport after AddToViewport or OnInitialised. In the latter case, the ViewportWidgets does not yet contain any elements, so the one with the Alighment set is added. As a result, Set Alignment in Viewport works as intended.
expect : red 2d box appears in the center of the white sphere
result : red 2d box appears slightly to the lower right of the sphere
There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-175311 in the post.
2 |
Component | UE - Editor - UI Systems - UMG |
---|---|
Affects Versions | 5.1, 5.2 |
Target Fix | 5.3 |
Created | Jan 27, 2023 |
---|---|
Resolved | Mar 31, 2023 |
Updated | Jan 8, 2024 |