A problem in TARRAY

Hi guys, I have two issues with TArray in UE4.16. TArray is always being collected by GC, despite declaring as UPROPERTY(). Secondly, when I try to pick object up through overlap function another time the number of TArray is increased again. However, as soon as the overlap function is done the TArray will be emptied. This the code

PickItem.h

#pragma once

#include “CoreMinimal.h”
#include “GameFramework/Actor.h”
#include “Components/BoxComponent.h”
#include “PickItem.generated.h”
UCLASS()
class INVENTORY_API APickItem : public AActor
{
GENERATED_BODY()

public:
// Sets default values for this actor’s properties
APickItem();

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

public:
// Called every frame
virtual void Tick(float DeltaTime) override;
UPROPERTY(EditAnywhere,BlueprintReadWrite,Category=Storage) USceneComponent *_RootS;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Storage) UStaticMeshComponent *_MeshOfItem;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = Storage) UBoxComponent _Container;
UPROPERTY(EditAnywhere)
TArray<APickItem
> _Inventory;

FRotator _Rotation;
UFUNCTION() void OnOverlapBegin( UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
UFUNCTION() void OnOverlapEnd( UPrimitiveComponent* OverlappedComp,  AActor* OtherActor,  UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
void PrintOut();
void HideTheItem(bool CheckVisibillity);
bool bStatuteOfOverLap;

};

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

#include “PickItem.h”
#include"Components/StaticMeshComponent.h"
#include"Engine.h"
// Sets default values
APickItem::APickItem()
{
// 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;
this->_RootS = CreateDefaultSubobject(TEXT(“SenceCo”));
this->_RootS = RootComponent;
this->_MeshOfItem = CreateDefaultSubobject(TEXT(“Mesh”));
this->_MeshOfItem->AttachToComponent(this->_RootS, FAttachmentTransformRules::SnapToTargetNotIncludingScale);
this->_Container = CreateDefaultSubobject(TEXT(“Holder”));
this->_Container->SetWorldScale3D(FVector(2, 2, 2));
this->_Container->AttachToComponent(_RootS, FAttachmentTransformRules::SnapToTargetNotIncludingScale);
this->_Container->bGenerateOverlapEvents = true;
this->_Container->OnComponentBeginOverlap.AddDynamic(this, &APickItem::OnOverlapBegin);
this->_Container->OnComponentEndOverlap.AddDynamic(this, &APickItem::OnOverlapEnd);
this->_Rotation = FRotator(0, 0, 0);
}

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

}

// Called every frame
void APickItem::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
this->_MeshOfItem->AddLocalRotation(this->_Rotation*DeltaTime);
PrintOut();
}

UFUNCTION() void APickItem::OnOverlapBegin(UPrimitiveComponent * OverlappedComp, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult & SweepResult)
{
if (OtherActor != NULL && OtherComp != NULL&& OtherActor != this)
{
this->bStatuteOfOverLap = true;
APickItem* ite = NewObject(this, FName(“ball”));

	this->_Inventory.Add(ite);
		
	GEngine->AddOnScreenDebugMessage(1, 3, FColor::Red, *(FString().FromInt(this->_Inventory.Num())));
		
	
}

}

UFUNCTION() void APickItem::OnOverlapEnd(UPrimitiveComponent * OverlappedComp, AActor * OtherActor, UPrimitiveComponent * OtherComp, int32 OtherBodyIndex)
{
if (OtherActor != NULL && OtherComp != NULL&& OtherActor != this)
{
this->bStatuteOfOverLap = false;
int n = this->_Inventory.Num();
}
}

void APickItem::PrintOut()
{

}

void APickItem::HideTheItem(bool CheckVisibillity)
{

}

Please format your code so it will be readable…

I can just answer right away only 1 part of your question:

“when I try to pick object up through overlap function another time the number of TArray is increased again.”

Thats right! , to avoid it you should swap this line “this->_Inventory.Add(ite);” with this line “this->_Inventory.AddUnique(ite);”

Thank you for replying me. I had changed to _Inventory.AddUnique(ite) before asking this, but I got the same result.Anyhow, sorry for mistyping the code

Ok I see now - " APickItem ite = NewObject(this, FName(“ball”));" you are creating new item each overlap event even with AddUnique it will be a different item - unless you will overload a “==” operator for it’s class…

For now it uses a default == operator which checks for the pointer equality - which is not equal in your case since while creating a new object it will create a new object (even if it has the same properties) and thus the pointers will not be equal.

Here is something to get you started Relational Operators Overloading in C++

And what do you get now with the string ?

this is the code

And what is the output after you started using FString ?
Is the Array grows each time you are overlapping the same item ?

If so then you can modify your if to the following

** if (OtherActor != NULL && OtherComp != NULL&& OtherActor != this && ! bStatuteOfOverLap) **

even when i use the regular add Like _Inventory.Add(this) the result still the same as soon the as
the function end the TArray will be emptied.

still the same outcome

My question is why GC is collecting the my array each time, there is no reason to be collected

Good Question - I think in 4.16 it had to be already fixed.
Try using an empty UPROPERTY() without anything inside the macro…

ok I am going to build the project right way

Unbelievable, is still the same result. The garbage collector collects the array

well there is a thing to try then:

It Can Work as a Work Around - but very ugly (and I would recommended to find whats wrong).

Try adding your object (not the FString) to the root.
And see if it gets cleared from the array

Because (I think that this is not a GC) GC fires once 60 secs or something like this - till then your object should still be alive for a while :).

nothing changes, moreover, a problem arises when the simulation is ended,UE4 crashes
down

Then your problem is NOT the scenario when GC clears out your TArray, whether something marks this to be deleted or you have some logical error somewhere.
AddToRoot wasn’t intended to fix your problem, it was intended to check the scenario where GC clears out TArray’s values (disregarding the retain of UPROPERTY) - now it is clearly NOT the case.

so what should I try. Is problem the release of UE4.16 because I have tried all I have got from knowledge in C++

No, there is no problem in 4.16 regards this issue AFAIK - I am using TArrays
that retaining a lot of stuff and even sharing it with multiple threads…
As soon as specified as PROPERTY() all work at my end, for now I am using 4.16.3.

You have couple of things to do:

a) Debug your Code (if you can’t debug probably due to intensity of mouse events) LOG everything you can.

b) Review your Logic (all of it not just the item.h) - who creates/allocates it ? how is it done ? could it be Collected by GC at some stage ?
(Probably who ever retains “this” is the problem I have a feeling that your item itself is rapidly allocates and deallocates – “Rubber duck”[1] is the way to go if you work alone.

I think I can not help you more than this suggestion, since I don’t have your code (and I am also too lazy to debug it for you even if i had :stuck_out_tongue: ).

[1] Rubber Duck method: Rubber duck debugging - Wikipedia