How to spawn N actors on every tick

Hi!

I have to spawn a lot of actors, around 8k, but when I do it, it freezes the game.

Someone has suggested me to spawn 10 every tick, but I don’t know how to do it: I know how to spawn ten, but I don’t know how to spawn them every tick.

How can I do it?

Here?

void MyActor::Tick(float DeltaSeconds)
{
   Super::Tick(DeltaSeconds);
}

Thanks!

ccp

header

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "MyActor.generated.h"

UCLASS()
class SPAWNPROJ_API AMyActor : public AActor
{
	GENERATED_BODY()
	
public:	

	AMyActor();

protected:

	virtual void BeginPlay() override;

public:	

	virtual void Tick(float DeltaTime) override;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	int maxActorsToSpawn = 8000;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	int spawnPerTick = 10;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UClass* ActorToSpawnClass;

	//UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FActorSpawnParameters SpawnParams;

private:
	TArray<AActor*> SpawnedActors;
	

};

cpp


#include "MyActor.h"

AMyActor::AMyActor()
{
	PrimaryActorTick.bCanEverTick = true;
}


void AMyActor::BeginPlay()
{
	Super::BeginPlay();
}

void AMyActor::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);
	if (SpawnedActors.Num() < maxActorsToSpawn) 
	{
		for (int i = 0; i < spawnPerTick; i++) 
		{
			if (SpawnedActors.Num() == maxActorsToSpawn) {
				break;
			}				
			AActor* SpawnedActor = GetWorld()->SpawnActor<AActor>(ActorToSpawnClass, GetTransform(), SpawnParams);
			SpawnedActors.Add(SpawnedActor);
		}
	}


}

1 Like

Thanks for your answer, @3dRaven

The method which spawns the actor is a method of a UGameInstanceSubsystem. I don’t know if this class has a Tick event and neither if it is a good idea to use your code in that event (in case if have it).

Probably I can create an Actor class to do it and instance it in the UGameInstanceSubsystem'smethod.

Thank you!

Header

#pragma once

#include "CoreMinimal.h"
#include "Subsystems/GameInstanceSubsystem.h"
#include "SpawnerSubsystem.generated.h"

/**
 * 
 */
UCLASS()
class YOUR_API USpawnerSubsystem : public UGameInstanceSubsystem, public FTickableGameObject
{
	GENERATED_BODY()
	
public:


	void Tick(float DeltaTime) override;
	bool IsTickable() const override;
	bool IsTickableInEditor() const override;
	bool IsTickableWhenPaused() const override;
	TStatId GetStatId() const override;

	UWorld* GetWorld() const override;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)	
	int maxActorsToSpawn = 8000;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	int spawnPerTick = 10;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	FTransform SpawnTransform;

	UPROPERTY(EditAnywhere, BlueprintReadWrite)
	UClass* ActorToSpawnClass;
	
	FActorSpawnParameters SpawnParams;



private:
	TArray<AActor*> SpawnedActors;

};

cpp

#include "SpawnerSubsystem.h"


void USpawnerSubsystem::Tick(float DeltaTime)
{
	if (SpawnedActors.Num() < maxActorsToSpawn)
	{
		for (int i = 0; i < spawnPerTick; i++)
		{
			if (SpawnedActors.Num() == maxActorsToSpawn) {
				break;
			}
			if (ActorToSpawnClass != nullptr) 
			{
				AActor* SpawnedActor = GetWorld()->SpawnActor<AActor>(ActorToSpawnClass, SpawnTransform, SpawnParams);
				SpawnedActors.Add(SpawnedActor);
			}
		}
	}
}

bool USpawnerSubsystem::IsTickable() const
{
	return true;
}

bool USpawnerSubsystem::IsTickableInEditor() const
{
	return false;
}

bool USpawnerSubsystem::IsTickableWhenPaused() const
{
	return false;
}

TStatId USpawnerSubsystem::GetStatId() const
{
	return TStatId();
}

UWorld* USpawnerSubsystem::GetWorld() const
{
	return GetOuter()->GetWorld();
}

Just be sure to set the spawned actor class somewhere via blueprints and set it’s transform

1 Like

I don’t know why, but I can’t set your answer as a solution.

Thank you!