Rapidly spawning / destroying actors

I have created a mirror system which rapidly spawns and destroys actors however whenever i try to spawn multiple at once and then destroy them soon after, my engine completely freezes up and i have to close it via task manager.

Heres my code for iterating through the array of pointers to spawned actors

for (int index = 0; index < Lasers.Num(); index++)
	{
		GEngine->AddOnScreenDebugMessage(index, 30.f, FColor::Red, FString(Lasers[index]->GetName()));
		if (!Lasers[index]) return;
		if (!Lasers[index]->IsValidLowLevel()) return;

		Lasers[index]->K2_DestroyActor();
		Lasers[index] = NULL;

	}
	Lasers.Empty();

Heres how i am spawning actors and adding them to the TArray

Beamref = GetWorld()->SpawnActor<ABeam>(Location, Rotation, SpawnInfo);
if (Beamref != nullptr)
{
	Cast<ABeam>(Beamref)->SetEnds(LaserStart, LaserEnd); UE_LOG(LogTemp, Warning, TEXT("Spawned"));
	Lasers.Add(Beamref); UE_LOG(LogTemp, Warning, TEXT("Added"));
}

The array is a simple TArray

TArray<ABeam*> Lasers;

Any help would be greatly appreciated!!

Hi! The question is - where are that methods? It is important to know when (in which order) and where (classes they belong to) they are called.

Header :

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

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "beam.h"
#include "Components/ArrowComponent.h"
#include "Colours.h"
#include "Laser.generated.h"



UCLASS()
class REFLECTIONPUZZLE_API ALaser : public AActor
{
	GENERATED_BODY()
	


public:	
	// Sets default values for this actor's properties
	ALaser();

	FTimerHandle StartLaserTimer;

	UFUNCTION()
		void StartCast();

	UPROPERTY()
		class UMaterial* LaserMaterial;

	UPROPERTY(EditAnywhere)
		TEnumAsByte<EColours> Colour;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		float Range = 99000;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FVector Direction;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		ABeam* Beamref;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FVector LaserStart;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FVector LaserEnd;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		FVector Origin;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		bool SensorActive = false;

	UPROPERTY(VisibleDefaultsOnly, Category = Extras)
		class UArrowComponent* Arrow1P;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
		TArray<ABeam*> Lasers;

	UFUNCTION(BlueprintCallable)
		void CastBeam(FVector LOrigin, FVector LDirection, float LDistance);


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

public:	
	// Called every frame
	virtual void Tick(float DeltaTime) override;

private:

	//TArray<ABeam*> Lasers;
	TArray<AActor*> FoundActors;
};

Hey thanks for your reply heres my header file and cpp : Laser.h - Pastebin.com Laser.cpp - Pastebin.com

CPP part 1

// Fill out your copyright notice in the Description page of Project Settings.
#include “Laser.h”
#include “Beam.h”
#include “DrawDebugHelpers.h”
#include “EngineUtils.h”
#include “CollisionQueryParams.h”
#include “Kismet/GameplayStatics.h”
#include “Math/Vector.h”

// Sets default values
ALaser::ALaser()
{
// 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;

Arrow1P = CreateDefaultSubobject<UArrowComponent>(TEXT("Arrow"));
Arrow1P->SetupAttachment(RootComponent);
Arrow1P->SetMobility(EComponentMobility::Movable);

LaserMaterial = CreateDefaultSubobject<UMaterial>(TEXT("LaserMaterial"));

}

// Called when the game starts or when spawned
void ALaser::BeginPlay()
{
Super::BeginPlay();
GetWorld()->GetTimerManager().SetTimer(StartLaserTimer, this, &ALaser::StartCast, 0.01f, true);
}

// Called every frame
void ALaser::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);

}

void ALaser::StartCast()
{

CastBeam(Arrow1P->GetComponentLocation() , Arrow1P->GetF

CPP part 2

void ALaser::CastBeam(FVector LOrigin, FVector LDirection, float Distance)
{

FVector BeamOrigin = LOrigin;
FVector BeamDirection = LDirection;
float BeamDistance = Distance;
UWorld* world = GetWorld();
FCollisionQueryParams TraceParams;

for (int index = 0; index < Lasers.Num(); index++)
{
	GEngine->AddOnScreenDebugMessage(index, 30.f, FColor::Red, FString(Lasers[index]->GetName()));
	if (!Lasers[index]) return;
	if (!Lasers[index]->IsValidLowLevel()) return;

	Lasers[index]->K2_DestroyActor();
	Lasers[index] = NULL;

}
Lasers.Empty();

bool Continue = true;
while (Continue)
{
	FHitResult Hit;
	DrawDebugLine(GetWorld(), BeamOrigin, (BeamOrigin + (BeamDirection * BeamDistance)), FColor::Red, false, 1, 0 , 1);

	bool cast = GetWorld()->LineTraceSingleByChannel(Hit, BeamOrigin, (BeamOrigin + (BeamDirection * BeamDistance)), ECC_Visibility, TraceParams);
	LaserStart = BeamOrigin;
	if (cast)
	{
		DrawDebugBox(world, Hit.ImpactPoint, FVector(5, 5, 5), FColor::Emerald, false, 2.0f);
		LaserEnd = Hit.ImpactPoint;
		bool HitComponent = Hit.Component->ComponentHasTag(TEXT("Reflect"));
		bool HitActor = Hit.Actor->ActorHasTag(TEXT("Reflect"));


		if (HitComponent || HitActor)
		{
			BeamOrigin = Hit.ImpactPoint;
			BeamDirection = BeamDirection.MirrorByVector(Hit.ImpactNormal);
			Continue = true;
		}
		else
		{
			Continue = false;
		}
	}
	else
	{
		LaserEnd = (BeamOrigin + (BeamDirection * BeamDistance));
		Continue = false;
	}

	FVector Location(0.0f, 0.0f, 0.0f);
	FRotator Rotation(0.0f, 0.0f, 0.0f);
	FActorSpawnParameters SpawnInfo;
	Beamref = GetWorld()->SpawnActor<ABeam>(Location, Rotation, SpawnInfo);
	if (Beamref != nullptr)
	{
		Cast<ABeam>(Beamref)->SetEnds(LaserStart, LaserEnd); UE_LOG(LogTemp, Warning, TEXT("Spawned"));
		Lasers.Add(Beamref); UE_LOG(LogTemp, Warning, TEXT("Added"));
	}
	else
	{
		UE_LOG(LogClass, Log, TEXT("NULL"));
	}
	
	

}

Dear valued Unreal Engine user,

This will potentially be really bad for performance. You might lock up the game-thread during the loop causing a stall, as well as creating too many actors before the previous ones are can be garbage collected can cause an Out of Memory crash.

In general for something like this you may either want to use instanced static meshes or Niagara particles, instead of multiple Actors. This will be better for performance and memory consumption. If you really do need to create many actors, you might benefit from doing that asynchronously, via a parallel for loop.

Thank you for your continued support,

Hello! Check out your while conditions! It seemed that it goes to infinity in hit cases (continue become TRUE and stay in this state forever).