I have PathFollow too, but not used with the pooled characters. Only special feature for the characters is footprintComponent, but its quite simple. Removed it but somehow it still gave reference error. Might test to remove it gain.
Any Actor containing a Pool Component should never be spawned at runtime as doing that, beyond possible issues, also make no sense since the Pool Component is meant to hold the pooled Actors in memory and keep them loaded until the map is unloaded or game closed.
(not pooled classes such as pooled projectile, the component which spawns pooled actors from pool only)
The actor with pool comp is spawned once and then stays in game until level is unloaded. I applied the logic that each weapon that player has chosen to carry for the level played will have a different projectile pool (each projectile differs a lot). I will send you details soon
i have emailed you with more details, hope this helps a bit
I have the blueprint, that have all pools, on world from start. So the error isnt connected to pool-blueprint spawning.
I will build another patch based on your logs and submit soon.
@GRADgr
Looking at these logs:
I believe there is really something very wrong within your LaserBlaster_BP uasset file or usage of it in game code by other Blueprints; maybe it is corrupted, I donāt know.
Iāve built 1.3.8 and submitting soon; this time you will be able to package, but if you get a crash when running the packaged game then that really means your LaserBlaster file is somehow messed up and this isnāt really a plugin bug at all, itās the Blueprint fileā¦ Sending 1.3.8 to Marketplace team now.
Thanks for update, this time getting the same thing only as a warning. Not as error. Going to see if the packaged demo launches once packing is finished.
Edit: Actually now I have a theory why it gives that error/warning. Cooking only map content and there is no characters placed on level. So probably it looses the whole blueprint since its not packaged, since it dosent have a reference?
Edit2: My theory was wrong, still warning (even I have one character placed on level manually per pooled character). But going to see if the packaged Project launches.
That error/warning means the Pool Component you have attached to the Spawn node is a NULL object.
That can only happen if the variable you have attached to the node is being cleared by something or some game code, the Pool Component variable should never be null; but the reason why it is an invalid object in your blueprint when you cook, this is beyond me.
Ok, very strange definitely. I didnt get yet Project launched. TrueSky plugin seems to be crashing the packaged build (edit: found out I need to copy-paste certain files to packaged build folder, but deleted it too early). Will take time to see if its only thing left, that prevent the launch.
Edit: Found out day or two old stagedBuild (packaged without BP compilation manager) and it started working already with the truesky trick. No issues with pooled characters with it. Soon testing with new packaged Project, but seems like there is no real issue.
It got Packaged on 4.17 for both windows and android, still am getting many many warnings for a lot of uassets, i will try to minimize them and i will send you logs to check.
Am still getting the PARSE ERROR, but this time only as a warning. thnx!!!
Packaged with BP compilation manager and no issues (even had that warning). Thanks for the plugin again and quick support.
Whatās the status on replicated actor support for this plugin (since network relevancy could automatically destroy/create objects at will)?
I didnāt participate in any multiplayer project making use of actor pooling, so I have no plans right now to officially add networking features to this pluginā¦
Although experienced developers on UE4 networking can do it by themselves.
Hello ,
Iāve just bought your plugin to handle the classic issue of projectile/bullet spawning.
So far, in C++ i have Reparent-ed my bullets from AActor to APooledActor, changed their ProjectileMovementComponent to your PooledProjectile .
in the level, i created a pool on an empty actor in the level using the Subclass of a bullet iām using as test.
Right now my bullets are spawned in C++ and destroyed in Blueprints.
Not 100% sure on how i should handle the spawning, and how to get a reference to the pool via C++.
This is how my bullets are spawned right now:
ABulletProjectile* Projectile = Cast<ABulletProjectile>(UGameplayStatics::BeginDeferredActorSpawnFromClass(this, ProjectileConfig.ProjectileClass, SpawnTM));
if (Projectile)
{
Projectile->Instigator = Instigator;
Projectile->SetOwner(this);
Projectile->InitVelocity(ShootDirection);
UGameplayStatics::FinishSpawningActor(Projectile, SpawnTM);
}
ShootDirection is used to set the āDirectionā of your Projectile Component.
I tried to check your example project but i canāt get it to work on 4.17 so iām a bit in the dark right now. Pretty sure iām close
That Blueprint demo example project would be something like this in C++ (without touching any blueprint side parameters)ā¦
(UE4.17) Example of a Pooled Actor class created in C++, named APlayerBulletRank3, with a Pooled Projectile Component attached:
PlayerBulletRank3.h
#pragma once
#include "OBJPool.h"
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "PlayerBulletRank3.generated.h"
UCLASS()
class POOL_API APlayerBulletRank3 : public APooledActor
{
GENERATED_BODY()
//
APlayerBulletRank3();
protected:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (DisplayName = "Projectile Component"))
UPooledProjectile* ProjectilePhyX;
public:
UPROPERTY(EditAnywhere, BlueprintReadOnly)
float BulletSpeed = 3000;
/// Manually fire this Projectile, instead of relying on Component Initialization.
UFUNCTION(Category = "Projectile", BlueprintNativeEvent, meta = (DisplayName = "Shoot", Keywords = "shoot projectile"))
void Shoot(); virtual void Shoot_Implementation();
/// Manually stops this Projectile, instead of relying on Component Destruction.
UFUNCTION(Category = "Projectile", BlueprintNativeEvent, meta = (DisplayName = "Break", Keywords = "break projectile"))
void Break(); virtual void Break_Implementation();
UFUNCTION()
void OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, FVector NormalImpulse, const FHitResult& Hit);
};
PlayerBulletRank3.cpp
#include "GAME.h"
#include "PlayerBulletRank3.h"
// Sets default values
APlayerBulletRank3::APlayerBulletRank3()
{
UStaticMeshComponent* ProjectileMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Projectile Mesh"));
RootComponent = ProjectileMesh;
static ConstructorHelpers::FObjectFinder<UStaticMesh> ProjectileAsset(TEXT("StaticMesh'/Game/TwinStick/Meshes/TwinStickProjectile.TwinStickProjectile'"));
if (ProjectileAsset.Succeeded()) { ProjectileMesh->SetStaticMesh(ProjectileAsset.Object); }
ProjectileMesh->SetEnableGravity(false);
ProjectileMesh->SetSimulatePhysics(true);
ProjectileMesh->bGenerateOverlapEvents = true;
ProjectileMesh->SetNotifyRigidBodyCollision(true);
ProjectileMesh->SetCollisionProfileName(FName("Projectile"));
ProjectileMesh->SetCollisionResponseToAllChannels(ECR_Ignore);
ProjectileMesh->SetCollisionResponseToChannel(ECC_Pawn,ECR_Block);
ProjectileMesh->SetCollisionResponseToChannel(ECC_WorldStatic,ECR_Block);
ProjectileMesh->SetCollisionResponseToChannel(ECC_WorldDynamic,ECR_Block);
ProjectileMesh->OnComponentHit.AddDynamic(this,&APlayerBulletRank3::OnHit);
//
ProjectilePhyX = CreateDefaultSubobject<UPooledProjectile>(TEXT("Projectile Component"));
ProjectilePhyX->MaxSpeed = BulletSpeed;
ProjectilePhyX->InitialSpeed = BulletSpeed;
ProjectilePhyX->Direction = FVector::ForwardVector;
OnPoolBeginPlay.AddDynamic(this,&APlayerBulletRank3::Shoot);
OnPoolEndPlay.AddDynamic(this,&APlayerBulletRank3::Break);
}
void APlayerBulletRank3::Shoot_Implementation() {
ProjectilePhyX->InitialSpeed = BulletSpeed;
ProjectilePhyX->MaxSpeed = BulletSpeed;
ProjectilePhyX->Shoot();
}
void APlayerBulletRank3::Break_Implementation() {
ProjectilePhyX->Break();
}
void APlayerBulletRank3::OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, FVector NormalImpulse, const FHitResult &Hit)
{
if (!OtherActor->IsValidLowLevelFast() || !OtherComponent->IsValidLowLevelFast()) {ReturnToPool(); return;}
//
if ((OtherActor != this) && OtherComponent->IsAnySimulatingPhysics()) {
OtherComponent->AddImpulseAtLocation(GetVelocity()*20,GetActorLocation(),NAME_None);
GEngine->AddOnScreenDebugMessage(1,1.f,FColor::Red,FString::Printf(TEXT("HIT! : %s"),*OtherActor->GetName()));
/// Apply here amount of damage to OtherActor based on Weapon/Bullet class...
}
//
ReturnToPool();
}
(UE4.17) Example of an Empty Actor created in C++, inside Gameās module, used as a container with a Pool Component attached, made to spawn bullets of type APlayerBulletRank3:
PlayerBulletRank3Pool.h
#pragma once
#include "PlayerBulletRank3.h"
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Runtime/Engine/Public/TimerManager.h"
#include "PlayerBulletRank3Pool.generated.h"
UCLASS()
class POOL_API APlayerBulletRank3Pool : public AActor
{
GENERATED_BODY()
//
APlayerBulletRank3Pool();
private:
UPROPERTY()
FTimerHandle TimerHandle;
protected:
UPROPERTY(EditDefaultsOnly, BlueprintReadOnly, meta = (DisplayName = "Pool Component"))
UObjectPool* BulletPool;
// Called when the game starts or when created
virtual void BeginPlay() override;
public:
UFUNCTION()
void Fire();
};
PlayerBulletRank3Pool.cpp
#include "GAME.h"
#include "PlayerBulletRank3Pool.h"
// Sets default values
APlayerBulletRank3Pool::APlayerBulletRank3Pool()
{
UBoxComponent* PoolRoot = CreateDefaultSubobject<UBoxComponent>(TEXT("Volume"));
PoolRoot->SetCollisionEnabled(ECollisionEnabled::NoCollision);
PoolRoot->SetCollisionObjectType(ECC_WorldStatic);
RootComponent = PoolRoot;
//
BulletPool = CreateDefaultSubobject<UObjectPool>(TEXT("Pool Component"));
BulletPool->TemplateClass = APlayerBulletRank3::StaticClass();
BulletPool->AutoInitialize = true;
BulletPool->PoolSize = 20;
}
// Called when the game starts or when created
void APlayerBulletRank3Pool::BeginPlay()
{
Super::BeginPlay();
//
const FTimerDelegate Timer = FTimerDelegate::CreateUObject(this,&APlayerBulletRank3Pool::Fire);
GetWorld()->GetTimerManager().SetTimer(TimerHandle,Timer,1.0f,true);
}
void APlayerBulletRank3Pool::Fire() {
bool Result;
FPoolSpawnOptions SpawnOptions;
SpawnOptions.ActorTickEnabled = true;
SpawnOptions.EnableCollision = true;
SpawnOptions.SimulatePhysics = true;
SpawnOptions.CollisionType = EPoolCollisionType::QueryAndPhysics;
//
FTransform SpawnTransform = FTransform(GetTransform().GetRotation().GetForwardVector().ToOrientationRotator(),GetTransform().GetTranslation(),FVector(1.f,1.f,1.f));
//
for (auto &BLT : BulletPool->GetInactiveObjects<APlayerBulletRank3>()) {
float BulletSpeed = FMath::RandRange(500,3000);
BLT->BulletSpeed = BulletSpeed;
}
//
auto Projectile = BulletPool->BeginDeferredSpawnFromPool(this,BulletPool,SpawnOptions,SpawnTransform,ESpawnActorCollisionHandlingMethod::AlwaysSpawn,this,false,Result);
auto Bullet = Cast<APlayerBulletRank3>(Projectile);
if (Bullet) {
BulletPool->FinishDeferredSpawnFromPool(Bullet,SpawnTransform);
UE_LOG(LogTemp,Warning,TEXT("{Pool}:: FIRED!"));
}
}
GAME.Build.cs:
PublicDependencyModuleNames.AddRange(new string] { "Core", "CoreUObject", "Engine", "InputCore" });
PrivateDependencyModuleNames.AddRange(new string] { "OBJPool" });
Now all it takes is placing the Empty Actor into the Gameās level.
If was this a weapon then Iād spawn from Pool a bullet in the location of the gunās barrel and using its axis orientation to automatically aim the bullet then just let it go.
Oh boy, thank you for your fast answer itās more than i needed !
rate 5 stars on Marketplace
Hi .
Iāve just bought this plugin hoping it will help me out. Although I now realise it may not perfectly drop into my project.
To cut a long story short, my blueprint creates lots of static mesh components to create 3d text (I have 256 static meshes for each character in the ascii set). My blueprint arranges these to form text, but itās hitching a lot of the time if there are quite a few characters. Am I right in thinking your plugin wonāt handle static mesh components? Should I instead create a generic blueprint actor which just contains a static mesh component which I can set?
What do you think?
Thanks
Your problem sounds like excessive drawcalls.
This plugin doesnāt batch drawcalls, so you wonāt see any performance gains from what youāre doing.
And yes, pooling happens on Actor level together with all its Components; creating or deleting Components wonāt make any use of the pooling system.
Thanks. Just to be clear - the hitch only happens when I spawn the mesh components, when itās done performance is fine. Actually, looking in to pooling may have given me an answer in that Iām going to try to make my own pool of SM components at startup - say 500 in an array, then reuse them rather than destroying and creating them as I do at the moment. This should eliminate the memory allocation part of the process which I gather may be the cause of the hitching.
thanks for the plugin anyway - I can use it in a separate part of the same project for some more performance gains.