20200904 UE4 AActor中初始化容器类的时机

问题描述

新建了一个继承于UObject的UClass,假设类名为ClassA

新建了一个继承于AActor的类,假设类名为ATest

ATest中定义了一个成员变量TArray<ClassA*> MyArray,并在「构造函数」中创建多个ClassA实例,逐一添加到MyArray中。

然后在ATest::Tick()中遍历MyArray,调用其中每一个元素的成员函数。

报空指针异常。

查看debug信息,可以看到MyArray中所有的元素都变成了nullptr

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
UCLASS()
class ClassA: public UObject
{
GENERATED_BODY()
public:
ClassA(){}

UFUNCTION()
Foo(){}
}

UCLASS()
class ATest: public AActor
{
GENERATED_BODY()
public:
ATest();

UFUNCTION()
void InitArray();

UFUNCTION()
void Tick();

UPROPERTY()
TArray<ClassA*> MyArray;
}

ATest::ATest()
{
this->InitArray();
}

void ATest::InitArray()
{
MyArray.Add(NewObject<ClassA>());
MyArray.Add(NewObject<ClassA>());
MyArray.Add(NewObject<ClassA>());
}

void ATest::Tick()
{
ClassA* Object = MyArray[0];
Object->Foo(); // <- 报空指针异常
}

疑惑

讲道理,我们都可以猜到明明添加进TArray的是正常的对象(debug可证),但是取出来却是个nullptr,这这个对象必定是被销毁了。

被销毁也就意味着引用计数变成了0。

经查,可得以下结论:

  • 声明为UPROPERTYUObject引用计数会加一
  • 被添加到TMap, TArray, TSet等UE4容器类的UObject的引用计数会加一
  • 执行了UObject::AddToRoot()之后引用计数也会加一

那么,为什么已经将TArray声明为UPROPERTY,还是会出现引用丢失呢?

解决手法

后来机缘巧合,把TArray元素的初始化从构造函数移动到了BeginPlay()就解决问题了。

原理

待研究。

Buy Me A Coffee / 捐一杯咖啡的钱
分享这篇文章~
0%
//