I’ll start by explaining the class layout I have. I’ll change names and skip irrelevant parts of the code to make it easier to understand, so if you see any mistakes that are too obvious or could lead to compilation errors, it’s likely that I simply made a mistake modifying that part.
The class that contains the array of arrays looks like this:
UCLASS()
class MYPROJECT_API UMyObject : public UObject
{
GENERATED_BODY()
public:
UMyObject();
UFUNCTION()
void Add(TScriptInterface<IMyInterface> element);
protected:
UPROPERTY()
TArray<FInternalArray> ElementCollection;
};
Where FInternalArray is a struct that I use as a workaround to the fact that UE doesn’t support TArrays of TArrays:
USTRUCT()
struct FInternalArray
{
GENERATED_BODY()
public:
UPROPERTY()
TArray<TScriptInterface<IMyInterface>> row;
};
This is how I initialize this 2D array:
UMyObject::UMyObject()
{
TArray<TScriptInterface<IMyInterface>> tmpArray;
for (uint16 i = 0; i < 7; i++)
{
ElementCollection.Add({tmpArray});
}
}
Now, here comes the issue. When I tried to add an element to the inner array, I noticed that, apparently, the outer array had been cleaned up. This is all that the Add() function does (index is always between 0 and 6):
void UMyObject::Add(TScriptInterface<IMyInterface> element, uint16 index)
{
UE_LOG(LogTemp, Warning, TEXT("ElementCollection.Num(): %d"), ElementCollection.Num())
ElementCollection[index].row.Add(element);
}
The values logged can be whatever:
ElementCollection.Num(): 7
ElementCollection.Num(): -1
ElementCollection.Num(): 7051781
...
And, either the line where I add an element to the inner array fails, or it succeeds and, then, I get an undefined reference error a few seconds after.
The class that has an instance of this UMyObject class looks like this:
UCLASS()
class MYPROJECT_API AMyCharacter : public ACharacter
{
protected:
// UPROPERTY()
UMyObject* Container;
...
Uncommenting the UPROPERTY() line above the declaration of Container makes the line where I print the number of elements in ElementContainer trigger an access violation (so it apparently makes GC kick in even sooner). This is the line:
UE_LOG(LogTemp, Warning, TEXT("ElementCollection.Num(): %d"), ElementCollection.Num())
Container is initialized like this:
AMyCharacter::AMyCharacter():
Super()
{
Container = NewObject<UMyObject>();
}
And I add elements to it this way:
Container->Add(NewElement, index);
I tried to initialize ElementCollection in other ways: with Emplace(), with Init(), etc. All of them yielded the same result.
As far as I’m aware, specifying UPROPERTY() should make the reflection system resgister the variable as a member of the class, hence the garbage collector shouldn’t be cleaning the outer array, or any of the arrays it contains.
I know that interfaces have several limitations in UE, but changing the types of the elements of the inner arrays to UObject* didn’t solve the issue either.
However, the fact that calling Num() on the outer array yields pretty much undefined values, makes me think that the GC may be somehow cleaning the content of the array. Or maybe I just can’t spot my mistake (which is likely).
I would appreciate if you could point out anything that I’m doing wrong.
Thanks in advance!