Download

Projectile Pool and missing/hidden projectiles

Hi there,

I have created a projectile pool to reuse my gunprojectiles instead of spawning and destroying them after i shot a gun.

My projectile pool manager spawns multible projectiles on loading the game. Those projectiles will be disabled (collision, movement), hidden and put into the AvailableProjectileArray.

The projectile will be put from AvailableProjectileArray into the ProjectilesInUseArray (to prevent garbage collection), actived and teleported to the muzzle position if i fire the gun.

The fired projectile will be put back from the ProjectilesInUseArray into the AvailableProjectileArray when it hits something or after 10 seconds flying straight without a hit. Also the projectile will be stopped, deactivated and hidden again.

On every shot i give out the actual amount of projectiles in my AvailableProjectileArray. The array is loosing and refilling projectiles after firing as expected. The problem is that sometimes there are invisible shots or no shots are happing when firing the gun.
It appears randomly: Sometimes i can fire multible magazines without problems, sometimes one or two shots are missing when firing a magazine and sometimes there is a full mag of “magical” projectiles which are invisible or not even there.

The amount of spawned projectiles in my pool is large enough, so i can not run out of bullets. I dont’ know whats going on. I think there must be a problem with the activation/disabling of the projectiles or the teleportation. Ore maybe the collision is not deactivated? But how is this possible when all projectiles get spawned with the same configuration and are using the same functions for activation and disabeling?

I post some code snippets. Maybe someone of you is a magican and find the problem. Thank you very much!

This is the configuration of the projectile when it gets spawn by the pool manager:


AUE4_Projectile::AUE4_Projectile(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
{
    CollisionComp = ObjectInitializer.CreateDefaultSubobject<USphereComponent>(this, TEXT("SphereComp"));
    CollisionComp->InitSphereRadius(5.0f);
    CollisionComp->SetSimulatePhysics(false);

    RootComponent = CollisionComp;

    ParticleComp = ObjectInitializer.CreateDefaultSubobject<UParticleSystemComponent>(this, TEXT("ParticleComp"));
    ParticleComp->bAutoActivate = false;
    ParticleComp->bAutoDestroy = false;
    ParticleComp->SetupAttachment(RootComponent);

    fProjectileSpeed = 0.0f;
    bProjectileShouldMove = false;

    fTimeToDestroyProjectile = 10.f;

    PrimaryActorTick.bCanEverTick = true;
}

/* Collision setup and disable mesh and collison after spawn before putting to pool */
void AUE4_Projectile::BeginPlay()
{
    Super::BeginPlay();


    CollisionComp->SetSimulatePhysics(false);

    //Simulate generate hit events
    CollisionComp->SetNotifyRigidBodyCollision(false);

    CollisionComp->SetCollisionEnabled(ECollisionEnabled::NoCollision);
    CollisionComp->SetCollisionObjectType(COLLISION_PROJECTILE);
    CollisionComp->SetCollisionResponseToAllChannels(ECR_Ignore);
    CollisionComp->SetCollisionResponseToChannel(ECC_WorldStatic, ECR_Block);
    CollisionComp->SetCollisionResponseToChannel(ECC_WorldDynamic, ECR_Block);
    CollisionComp->SetCollisionResponseToChannel(ECC_Pawn, ECR_Block);
    CollisionComp->OnComponentHit.AddDynamic(this, &AUE4_Projectile::OnCompHit);
}


Here i’am activating the projectile after teleportated it to the gun muzzle:


void AUE4_Projectile::InitializeAfterPickedFromPool(FVector ShootDir, TSubclassOf<class AUE4_Projectile> ProjectileTypeNeeded)
{
    ShotDirection = ShootDir;

    ProjectileClass = ProjectileTypeNeeded;

    //GetActorsOwner
    AUE4_Weapon* MyOwnerWeapon = Cast<AUE4_Weapon>(GetOwner());

    if (IsValid(MyOwnerWeapon))
    {
        MyOwnerWeapon->ApplyBasicWeaponConfig(MyWeaponConfig);
    }

    MyController = GetInstigatorController();


    CollisionComp->MoveIgnoreActors.Add(Instigator);
    CollisionComp->SetSimulatePhysics(true);

    //Simulate generate hit events
    CollisionComp->SetNotifyRigidBodyCollision(true);
    CollisionComp->SetCollisionEnabled(ECollisionEnabled::PhysicsOnly);

    fProjectileSpeed = 2000.0f;

    SetActorHiddenInGame(false);
    SetActorTickEnabled(true);

    //Instead of set life span
    GetWorld()->GetTimerManager().SetTimer(TimerHandle_LifeTimeForPooledProjectile, this, &AUE4_Projectile::PutNotNeedetProjectileBackToPool, MyWeaponConfig.ProjectileLife, false);

    //Start moving
    bProjectileShouldMove = true;
}


This is the code to disable the projectile when putting it back to the pool


void AUE4_Projectile::DisableAndHideProjectileForPool()
{
    //Reset values
    this->Instigator = nullptr;
    this->SetOwner(nullptr);

    fProjectileSpeed = 0.0f;
    SetActorHiddenInGame(true);
    SetActorTickEnabled(false);

    CollisionComp->SetSimulatePhysics(false);

    //Simulate generate hit events
    CollisionComp->SetNotifyRigidBodyCollision(false);
    CollisionComp->SetCollisionEnabled(ECollisionEnabled::NoCollision);    

    bProjectileShouldMove = false;
}

And here i teleport the projectile from the pool to the weapon muzzle to fire a shot:


void AUE4_AssaultRifle::FireProjectile(FVector Origin, FVector_NetQuantizeNormal ShootDir)
{
    //Grunt game mode
    AUE4_GameMode* IsDefaultGameMode = Cast<AUE4_GameMode>(GetWorld()->GetAuthGameMode());

    AUE4_ProjectilePoolManager* WorldsProjectileManager = IsDefaultGameMode->GetProjectileManager();

    if (IsValid(WorldsProjectileManager))
    {
        AUE4_Projectile* MyNeedetProjectile = WorldsProjectileManager->GetProjectileFromPool(WeaponConfig.ProjectileClass);

        MyNeedetProjectile->Instigator = Instigator;
        MyNeedetProjectile->SetOwner(this);
        MyNeedetProjectile->SetActorLocation(Origin, false, nullptr, ETeleportType::TeleportPhysics);
        MyNeedetProjectile->SetActorRotation(ShootDir.Rotation(), ETeleportType::TeleportPhysics);

        MyNeedetProjectile->InitializeAfterPickedFromPool(ShootDir, WeaponConfig.ProjectileClass);
    }
}

Allright, problem solved. It was my fault. I had deactivated the particle system itself after the bullet hit something and not reactivated it. :rolleyes: