Метод OnConstruction () класса Actor в Unreal Engine выполняется неправильно - PullRequest
0 голосов
/ 20 марта 2019

Я пишу класс ALadder на C ++, вдохновленный учебником Алана Нун https://www.youtube.com/watch?v=axuwbkDWI5U. В настоящее время класс очень прост:

Ladder.h

#pragma once

#include "GameFramework/Actor.h"

#include "Ladder.generated.h"

class UPaperSprite;

UCLASS()
class ALadder : public AActor
{
    GENERATED_BODY()

public:

    ALadder();

    virtual void OnConstruction(const FTransform& Transform) override;

protected:

    UPROPERTY(EditAnywhere, Meta = (MakeEditWidget = true))
        FVector TopVector{FVector(0.0f, 0.0f, 100.0f)};

    UPROPERTY(EditAnywhere, Meta = (MakeEditWidget = true))
        FVector BottomVector{FVector(0.0f, 0.0f, 0.0f)};

    UPROPERTY(EditAnywhere)
        float RungOffset{ 10.0f };

    UPROPERTY(EditAnywhere)
        UPaperSprite* RungSprite {};

private:
};

Ladder.cpp

#include "Actors/Ladder.h"
#include "PaperSprite.h"
#include "PaperSpriteComponent.h"
#include "UObject/UObjectIterator.h"

ALadder::ALadder() 
{
    RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootSceneComponent"));
}

void ALadder::OnConstruction(const FTransform& Transform)
{
    Super::OnConstruction(Transform);

    BottomVector = FVector(0.0f);
    TopVector.X = 0.0f;
    TopVector.Y = 0.0f;

    TArray<UActorComponent*> SpriteComponents = GetComponentsByClass(UPaperSpriteComponent::StaticClass());
    // Remove all components
    for (auto It = SpriteComponents.CreateIterator(); It; It++)
    {
        (*It)->DestroyComponent();
    }

    UPaperSpriteComponent* SpriteComponent = nullptr;
    float Diff_Z = (TopVector - BottomVector).Z;
    if (Diff_Z < 0.0f)
    {
        TopVector = BottomVector;
    }

    int32 RungsNumber = (int)(Diff_Z / RungOffset);
    // Add components
    for (int32 i = 0; i <= RungsNumber; ++i)
    {
        SpriteComponent = NewObject<UPaperSpriteComponent>(this);
        FAttachmentTransformRules AttachmentRules(EAttachmentRule::KeepRelative, false);
        SpriteComponent->AttachToComponent(RootComponent, AttachmentRules);
        SpriteComponent->SetRelativeLocation(FVector(0.0f, 0.0f, RungOffset * i));
        SpriteComponent->SetSprite(RungSprite);
        SpriteComponent->SetCollisionEnabled(ECollisionEnabled::NoCollision);
    }
}

Когда я пытаюсь изменить TopVector с помощью виджета в редакторе, цепочки не появляются, но когда я пытаюсь изменитьЗначение по умолчанию TopVector на панели Details, работает корректно.Я заметил, что когда я использовал виджет TopVector, ALadder :: OnConstruction () вызывался дважды;это два разных стека вызовов:

Первый стек вызовов:

>   UE4Editor-platformer-6449.dll!ALadder::OnConstruction(const FTransform & Transform) Line 13 C++
    UE4Editor-Engine.dll!AActor::ExecuteConstruction(const FTransform & Transform, const FRotationConversionCache * TransformRotationCache, const FComponentInstanceDataCache * InstanceDataCache, bool bIsDefaultTransform) Line 839   C++
    UE4Editor-Engine.dll!AActor::RerunConstructionScripts() Line 494    C++
    UE4Editor-Engine.dll!AActor::PostEditChangeProperty(FPropertyChangedEvent & PropertyChangedEvent) Line 125  C++
    UE4Editor-UnrealEd.dll!FEdMode::InputDelta(FEditorViewportClient * InViewportClient, FViewport * InViewport, FVector & InDrag, FRotator & InRot, FVector & InScale) Line 378    C++
    UE4Editor-PlacementMode.dll!FPlacementMode::InputDelta(FEditorViewportClient * InViewportClient, FViewport * InViewport, FVector & InDrag, FRotator & InRot, FVector & InScale) Line 437    C++
    UE4Editor-UnrealEd.dll!FEditorModeTools::InputDelta(FEditorViewportClient * InViewportClient, FViewport * InViewport, FVector & InDrag, FRotator & InRot, FVector & InScale) Line 729   C++
    UE4Editor-UnrealEd.dll!FEditorViewportClient::InputWidgetDelta(FViewport * InViewport, EAxisList::Type CurrentAxis, FVector & Drag, FRotator & Rot, FVector & Scale) Line 3283  C++
    UE4Editor-UnrealEd.dll!FLevelEditorViewportClient::InputWidgetDelta(FViewport * InViewport, EAxisList::Type InCurrentAxis, FVector & Drag, FRotator & Rot, FVector & Scale) Line 2383   C++
    UE4Editor-UnrealEd.dll!FEditorViewportClient::UpdateMouseDelta() Line 2130  C++
    UE4Editor-UnrealEd.dll!FEditorViewportClient::Tick(float DeltaTime) Line 1180   C++
    UE4Editor-UnrealEd.dll!FLevelEditorViewportClient::Tick(float DeltaTime) Line 2138  C++
    UE4Editor-UnrealEd.dll!UEditorEngine::Tick(float DeltaSeconds, bool bIdleMode) Line 1800    C++
    UE4Editor-UnrealEd.dll!UUnrealEdEngine::Tick(float DeltaSeconds, bool bIdleMode) Line 403   C++
    UE4Editor.exe!FEngineLoop::Tick() Line 3699 C++
    [Inline Frame] UE4Editor.exe!EngineTick() Line 62   C++
    UE4Editor.exe!GuardedMain(const wchar_t * CmdLine, HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, int nCmdShow) Line 174   C++
    UE4Editor.exe!WinMain(HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, char * __formal, int nCmdShow) Line 262   C++
    [External Code] 

Второй стек вызовов:

>   UE4Editor-platformer.dll!ALadder::OnConstruction(const FTransform & Transform) Line 13  C++
    UE4Editor-Engine.dll!AActor::ExecuteConstruction(const FTransform & Transform, const FRotationConversionCache * TransformRotationCache, const FComponentInstanceDataCache * InstanceDataCache, bool bIsDefaultTransform) Line 839   C++
    UE4Editor-Engine.dll!AActor::RerunConstructionScripts() Line 494    C++
    UE4Editor-Engine.dll!AActor::PostEditMove(bool bFinished) Line 147  C++
    UE4Editor-UnrealEd.dll!FLevelEditorViewportClient::TrackingStopped() Line 2910  C++
    UE4Editor-UnrealEd.dll!FMouseDeltaTracker::EndTracking(FEditorViewportClient * InViewportClient) Line 306   C++
    UE4Editor-UnrealEd.dll!FEditorViewportClient::StopTracking() Line 2655  C++
    UE4Editor-UnrealEd.dll!FEditorViewportClient::InputKey(FViewport * InViewport, int ControllerId, FKey Key, EInputEvent Event, float __formal, bool __formal) Line 2590  C++
    UE4Editor-UnrealEd.dll!FLevelEditorViewportClient::InputKey(FViewport * InViewport, int ControllerId, FKey Key, EInputEvent Event, float AmountDepressed, bool bGamepad) Line 2607  C++
    UE4Editor-Engine.dll!FSceneViewport::OnMouseButtonUp(const FGeometry & InGeometry, const FPointerEvent & InMouseEvent) Line 566 C++
    UE4Editor-Slate.dll!SViewport::OnMouseButtonUp(const FGeometry & MyGeometry, const FPointerEvent & MouseEvent) Line 202 C++
    [Inline Frame] UE4Editor-Slate.dll!FSlateApplication::RoutePointerUpEvent::__l13::<lambda_8aae5586f97da0914c7f98177fd6d3e0>::operator()(const FArrangedWidget &) Line 5592  C++
    UE4Editor-Slate.dll!FEventRouter::Route<FReply,FEventRouter::FBubblePolicy,FPointerEvent,<lambda_8aae5586f97da0914c7f98177fd6d3e0> >(FSlateApplication * ThisApplication, FEventRouter::FBubblePolicy RoutingPolicy, FPointerEvent EventCopy, const FSlateApplication::RoutePointerUpEvent::__l13::<lambda_8aae5586f97da0914c7f98177fd6d3e0> & Lambda) Line 270 C++
    UE4Editor-Slate.dll!FSlateApplication::RoutePointerUpEvent(FWidgetPath & WidgetsUnderPointer, FPointerEvent & PointerEvent) Line 5576   C++
    UE4Editor-Slate.dll!FSlateApplication::ProcessMouseButtonUpEvent(FPointerEvent & MouseEvent) Line 6087  C++
    UE4Editor-Slate.dll!FSlateApplication::OnMouseUp(const EMouseButtons::Type Button, const FVector2D CursorPos) Line 6060 C++
    UE4Editor-ApplicationCore.dll!FWindowsApplication::ProcessDeferredMessage(const FDeferredWindowsMessage & DeferredMessage) Line 1831    C++
    UE4Editor-ApplicationCore.dll!FWindowsApplication::DeferMessage(TSharedPtr<FWindowsWindow,0> & NativeWindow, HWND__ * InHWnd, unsigned int InMessage, unsigned __int64 InWParam, __int64 InLParam, int MouseX, int MouseY, unsigned int RawInputFlags) Line 2281    C++
    UE4Editor-ApplicationCore.dll!FWindowsApplication::ProcessMessage(HWND__ * hwnd, unsigned int msg, unsigned __int64 wParam, __int64 lParam) Line 1511   C++
    UE4Editor-ApplicationCore.dll!FWindowsApplication::AppWndProc(HWND__ * hwnd, unsigned int msg, unsigned __int64 wParam, __int64 lParam) Line 766    C++
    [External Code] 
    [Inline Frame] UE4Editor-ApplicationCore.dll!WinPumpMessages() Line 107 C++
    UE4Editor-ApplicationCore.dll!FWindowsPlatformApplicationMisc::PumpMessages(bool bFromMainLoop) Line 130    C++
    UE4Editor.exe!FEngineLoop::Tick() Line 3615 C++
    [Inline Frame] UE4Editor.exe!EngineTick() Line 62   C++
    UE4Editor.exe!GuardedMain(const wchar_t * CmdLine, HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, int nCmdShow) Line 174   C++
    UE4Editor.exe!WinMain(HINSTANCE__ * hInInstance, HINSTANCE__ * hPrevInstance, char * __formal, int nCmdShow) Line 262   C++
    [External Code] 

Ответы [ 2 ]

0 голосов
/ 15 мая 2019

Функция OnConstruction () предназначена для повторной инициализации вещей специально для сценария использования при каждом изменении UPROPERTY в Редакторе.Я полагаю, что ваш код в конечном итоге имеет функциональность, аналогичную функциям UE4 CreateDefaultSubobject и SetupAttachment.«Правильный» способ сделать это - создать ваши компоненты в конструкторе ALadder :: ALadder (), аналогично этому учебнику: https://docs.unrealengine.com/en-us/Programming/Tutorials/Components/1

RegisterComponent является своего рода исправлением-up функция, которая запускается в конце процесса создания компонента.Причина изменения работающего значения заключается в том, что это действие снова вызвало функцию OnConstruction ().

0 голосов
/ 20 марта 2019

Может быть, я нашел решение, но я не совсем понял, почему оно работает. После создания нового компонента я вызываю метод UActorComponent :: RegisterComponent (), и это решает проблему. Кто-нибудь знает, почему это работает? Странным фактом является то, что раньше он работал правильно только в том случае, если я изменил TopVector на панели сведений.

...