Ok, so I am really hitting a wall here and I figured I might as well ask since I have seen no mention of a similar problem after extensive research throughout forums.
I have a class called AS_BoardPawn inheriting from the APawn class and I need to spawn a Blueprint object derived from a C++ class which is a simple mesh that is spawned when the player clicks a spot on the screen and is destroyed when the player releases the click. I found information on how to spawn said Blueprint class and it works as it should, however for some reason under two circumstances the editor crashes.
- When I click “Stop Simulation”
- When I wait while the mesh is on the screen (about 1-2 minutes, probably garbage collection ?)
When debugging with VS I get an Exception in UObjectBase.h at line 125
FORCEINLINE UObject* GetOuter() const
{
return OuterPrivate;
}
Now, my assumption is that UE4 is accessing a stale pointer which leads to one of my classes (the Pawn class ?) but I have no idea how to fix this, I’ve tried quite a few things, but nothing seems to work.
The function for spawning the actor :
AEffectLine* AS_BoardPawn::SpawnEffectLine(FVector location)
{
AEffectLine* newEffectLine = 0;
if (effectLine)
{
FActorSpawnParameters SpawnParams;
FRotator rotator = FRotator(0.0f);
newEffectLine = GetWorld()->SpawnActor<AEffectLine>(effectLine, location, rotator, SpawnParams);
}
return newEffectLine;
}
with effectLine being a UClass* (I changed it from SubClassOf after seeing mentions of it causing issues, but to no avail)
If it can be of any help, here is the whole Tick function where effectLineInst is a AEffectLine* and selectionLines is a TArray of AEffectLine*
void AS_BoardPawn::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (clicking)
{
//Update effectLine
if (effectLineInst)
{
playerCtrl->DeprojectMousePositionToWorld(mouseLocation, mouseDirection);
projMousePosition = this->GetActorLocation() - (projHeight / mouseDirection.Z) * mouseDirection;
AEffectLine* eLine = Cast<AEffectLine>(effectLineInst);
if (eLine != nullptr)
{
eLine->UpdateSplineSimple(projMousePosition);
}
}
clickingUpdate = true;
if (selectedLamps.Num() <= loopLength)
{
//Gets the hit result of objects under the mouse
FHitResult* hit = new FHitResult;
playerCtrl->GetHitResultUnderCursor(ECC_WorldStatic, false, *hit);
AActor* hitActor = hit->GetActor();
bool debugBool = selectedLamps.Contains(hitActor);
//Check if the lamp is valid and not already in the array
if (hitActor && hitActor->IsA(ALamp::StaticClass()) && (!selectedLamps.Contains(hitActor) &&
selectedLamps.Num() < loopLength || selectedLamps.Num() > 0 && hitActor == selectedLamps[0] && hitActor != selectedLamps.Last()))
{
bool isClear = false;
if (selectedLamps.Num() > 0)
{
FHitResult* pathHit = new FHitResult;
//Line trace between the last lamp and the new one to find if path is clear
FVector Start = selectedLamps.Last()->GetActorLocation();
FVector End = hitActor->GetActorLocation();
if (FVector::DistSquared(Start, End) < 9000000.0f)
{
FCollisionQueryParams* TraceParams = new FCollisionQueryParams();
ALamp* Startlamp = Cast<ALamp>(selectedLamps.Last());
Startlamp->SetActorEnableCollision(false);
isClear = !GetWorld()->LineTraceSingleByChannel(*pathHit, Start, End, ECC_WorldStatic, TraceParams);
Startlamp->SetActorEnableCollision(true);
if (pathHit->GetActor() && pathHit->GetActor()->IsA(ALamp::StaticClass()))
isClear = true;
}
}
else
{
isClear = true;
}
if (isClear) //The lamp selection is validated
{
ALamp* lamp = Cast<ALamp>(hitActor);
lamp->SetLampState(true);
selectedLamps.Add(hitActor);
FVector lampLocation = hitActor->GetActorLocation();
if (effectLineInst)
{
AEffectLine* eLine = Cast<AEffectLine>(effectLineInst);
if (eLine != nullptr)
{
eLine->UpdateSplineSimple(FVector(lampLocation.X, lampLocation.Y, effectLineHeight));
}
selectionLines.Add(effectLineInst);
}
effectLineInst = SpawnEffectLine(FVector(lampLocation.X, lampLocation.Y, effectLineHeight));
}
}
}
}
else if (clickingUpdate)
{
clickingUpdate = false;
//If loop was not completed
if (selectedLamps.Num() > 0 && selectedLamps.Last() != selectedLamps[0])
{
//Turns off lamps
uint8 arrayLength = selectedLamps.Num();
for (uint8 i = 0; i < arrayLength; ++i)
{
ALamp* lamp = Cast<ALamp>(selectedLamps[i]);
lamp->SetLampState(false);
}
//Clears electric lines
arrayLength = selectionLines.Num();
for (uint8 i = 0; i < arrayLength; ++i)
{
if (selectionLines[i])
{
selectionLines[i]->Destroy();
}
}
}
if (effectLineInst)
{
effectLineInst->Destroy();
}
delete effectLineInst;
effectLineInst = 0;
selectedLamps.Empty();
}
}
It’s probably also worth mentioning that all class variables are declared with UPROPERTY
I am really at a loss here, thank you in advance