我不明白问题是什么。我创建了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
答案 0 :(得分:0)
这实际上不是UE4类的工作方式;有点头疼。
UCLASS 构造函数在构造时(并非您期望使用“普通” C ++对象),不是在对象(即类的实例)上调用的函数。该类构造函数负责构造 Class Default Object (CDO)。然后在实例化类时将CDO用作模板。类似地,CDO是用于创建其他对象的类的“主磁盘”实例。您的 UCLASS 构造函数仅在CDO上调用过一次。
因此,通过调用NewObject
,您创建了一个新对象,并将指向该对象的指针分配给CDO的obj
成员。然后,您继续创建世界上actor的实例,并且指针为null。您的对象尚未被垃圾回收;从来没有分配过它。
您需要呼叫NewObject
而不是CreateDefaultSubobject
。这告诉CDO,在实例化AMyActor
actor时,应创建模板指定类型的新对象。 NewObject
用于在演员的生命周期中的PreInitializeComponents
和EndPlay
之间动态生成的对象。
TL; DR :如果要在构造函数中调用,请将NewObject
调用更改为CreateDefaultSubobject
。或者,将NewObject
调用移至演员的PostInitializeComponents
函数。
https://docs.unrealengine.com/en-us/Programming/UnrealArchitecture/Objects https://docs.unrealengine.com/en-us/Programming/UnrealArchitecture/Actors/ActorLifecycle
NB。请注意,提供的“对象”文档链接已经过时(v4.11;我注意到它引用了ConstructObject
,此后已弃用并删除了该链接)。但是,在撰写本文时,它关于CDO的说法并没有改变(4.21)。