unreal-engine4 - Actor 构造后 UPROPERTY 被破坏

标签 unreal-engine4

我不明白问题出在哪里。我创建了 2 个类 AMyActor 和 UObject。在 AMyActor 中,有一个 UObject 字段标记为属性。由于某种原因,在 AMyActor 构造函数之后,垃圾收集器删除了 UObject 对象。

MyActor.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "MyObject.h"
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"

UCLASS()
class MYPROJECT2_API AMyActor : public AActor
{
    GENERATED_BODY()

public: 
    // Sets default values for this actor's properties
    AMyActor();

protected:
    // Called when the game starts or when spawned
    virtual void BeginPlay() override;

public: 
    // Called every frame
    virtual void Tick(float DeltaTime) override;

    UPROPERTY()
    UObject *obj;

    UPROPERTY(EditAnywhere)
    UStaticMeshComponent *mesh;
};

MyActor.cpp

// Fill out your copyright notice in the Description page of Project Settings.

#include "MyActor.h"


// Sets default values
AMyActor::AMyActor()
{
    // Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    PrimaryActorTick.bCanEverTick = true;
    obj = NewObject<UMyObject>();
    mesh = CreateDefaultSubobject<UStaticMeshComponent>("ms");
    UE_LOG(LogTemp, Warning, TEXT("actor create %d %d"), this, obj);
}

// Called when the game starts or when spawned
void AMyActor::BeginPlay()
{
    Super::BeginPlay();

}

// Called every frame
void AMyActor::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
    UE_LOG(LogTemp, Warning, TEXT("actor %d %d"), this, obj);
}

MyObject.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "UObject/NoExportTypes.h"
#include "MyObject.generated.h"

/**
 * 
 */
UCLASS()
class MYPROJECT2_API UMyObject : public UObject
{
    GENERATED_BODY()

    UMyObject()
    {
        UE_LOG(LogTemp, Warning, TEXT("object create %d"), this);
    }

    ~UMyObject()
    {
        UE_LOG(LogTemp, Warning, TEXT("object destroy %d"), this);
    }
};

输出

PIE: New page: PIE session: Minimal_Default (Feb 17, 2019, 7:48:39 PM)
LogPlayLevel: Creating play world package: /Game/StarterContent/Maps/UEDPIE_0_Minimal_Default
LogTemp: Warning: object create 1801824896
LogTemp: Warning: actor create 1441518592 1801824896
LogPlayLevel: PIE: StaticDuplicateObject took: (0.005484s)
LogAIModule: Creating AISystem for world Minimal_Default
LogPlayLevel: PIE: World Init took: (0.001288s)
LogPlayLevel: PIE: Created PIE world by copying editor world from /Game/StarterContent/Maps/Minimal_Default.Minimal_Default to /Game/StarterContent/Maps/UEDPIE_0_Minimal_Default.Minimal_Default (0.007418s)
LogTemp: Warning: object destroy 1801824896
LogInit: XAudio2 using 'Speakers (Realtek High Definition Audio(SST))' : 2 channels at 48 kHz using 32 bits per sample (channel mask 0x3)
LogInit: FAudioDevice initialized.
LogUObjectGlobals: Warning: Failed to find object 'Class /Script/MyProject2.MyProject2GameMode'
LogLoad: Game class is 'GameModeBase'
LogWorld: Bringing World /Game/StarterContent/Maps/UEDPIE_0_Minimal_Default.Minimal_Default up for play (max tick rate 60) at 2019.02.17-17.48.39
LogWorld: Bringing up level for play took: 0.002244
LogContentBrowser: Native class hierarchy updated for 'MovieSceneCapture' in 0.0004 seconds. Added 10 classes and 0 folders.
PIE: Play in editor start time for /Game/StarterContent/Maps/UEDPIE_0_Minimal_Default 0.179
LogBlueprintUserMessages: Late PlayInEditor Detection: Level '/Game/StarterContent/Maps/Minimal_Default.Minimal_Default:PersistentLevel' has LevelScriptBlueprint '/Game/StarterContent/Maps/Minimal_Default.Minimal_Default:PersistentLevel.Minimal_Default' with GeneratedClass '/Game/StarterContent/Maps/Minimal_Default.Minimal_Default_C' with ClassGeneratedBy '/
Game/StarterContent/Maps/Minimal_Default.Minimal_Default:PersistentLevel.Minimal_Default'
LogTemp: Warning: actor 1441518592 0
LogTemp: Warning: actor 1441518592 0
LogTemp: Warning: actor 1441518592 0
LogTemp: Warning: actor 1441518592 0
LogTemp: Warning: actor 1441518592 0
LogTemp: Warning: actor 1441518592 0
LogTemp: Warning: actor 1441518592 0

最佳答案

UE4 类实际上并不是这样工作的;这有点令人困惑。

UCLASS 构造函数不是在构造对象(即类的实例)时调用的函数(正如您期望使用“普通”C++ 对象一样)。相反,类构造函数负责构造类默认对象 (CDO)。然后,在实例化类时,将 CDO 用作模板。类似地,CDO 是用于创建其他对象的类的“母盘”实例。您的UCLASS构造函数仅被调用一次:在CDO上。

因此,通过调用 NewObject,您创建了一个新对象,并将指向该对象的指针分配给 CDO 的 obj 成员。然后,您继续创建世界中 Actor 的实例,并且您的指针为空。你的对象还没有被垃圾回收;它从一开始就没有被分配。

您需要调用的是CreateDefaultSubobject,而不是NewObject。这告诉 CDO 当您的 AMyActor actor 实例化时,应该创建一个模板指定类型的新对象。 NewObject 用于在 actor 生命周期中的 PreInitializeComponentsEndPlay 之间调用动态生成的对象。

TL;DR:如果您想在构造函数中调用 NewObject 调用,请将其更改为 CreateDefaultSubobject。或者将 NewObject 调用移至 Actor 的 PostInitializeComponents 函数。

https://docs.unrealengine.com/en-us/Programming/UnrealArchitecture/Objects https://docs.unrealengine.com/en-us/Programming/UnrealArchitecture/Actors/ActorLifecycle

注意。请注意,所提供的对象文档链接已严重过时(v4.11;我注意到它引用了 ConstructObject,该链接已被弃用并删除)。然而,在撰写本文时,关于 CDO 的内容并未改变 (4.21)。

关于unreal-engine4 - Actor 构造后 UPROPERTY 被破坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54735067/

相关文章:

c++ - 我无法创建虚幻引擎 4 c++ 项目

.net - 无法在 Linux 上生成 UE5 项目文件

c++ - 为什么虚幻引擎中的变量为空?

unreal-engine4 - 将用 C++/OpenGL 编写的手机游戏移植到 UE4

unreal-engine4 - 编译虚幻 Lightmass。在 Linux 上从源代码构建 Unreal 4.24 时出现错误

multithreading - 来自子 CPU 线程的 Vulkan Compute 调度

c++ - 在 Pawn 的骨架网格物体上播放动画

c++ - UE4和Azure存储SDK

c++ - 虚幻引擎 4.16,C++ 包含头文件

c++ - UE4 C++ 将字符串转换为 double