Download

Binding to 'OnDestroyed' before actor is actually destroyed

The powerup spawner in my game spawns a new powerup five seconds after someone has picked up the last one it spawned. Players are allowed to stand on the powerup’s spawnpoint and receive it immediately once the powerup has spawned. I am detecting when the powerup is picked up by subscribing to its OnDestroyed delegate since it is destroyed upon pickup (handled through OnComponentOverlapBegins). What seems to be happening is that if someone does indeed camp the spawnpoint, the collision will occur and OnDestroyed will be called before I can even subscribe to it in code.

Here’s the code in case I’m not being clear:



    FActorSpawnParameters spawnParams;
    spawnParams.bNoCollisionFail = true;
    spawnParams.bNoFail = true;
    spawnParams.Owner = this;
    LastSpawnedPowerupActor = GetWorld()->SpawnActor(targetClass, &startPosition, &FRotator::ZeroRotator, spawnParams);
    check(LastSpawnedPowerupActor != nullptr);

    // at this point, the powerup has already been collided with so OnDestroyed has already been called
    // so subscribing to the powerup will do nothing, assuming that the player is camping the powerup spawn

    // subscribe to destruction of next object

    if (ShouldRandomize)
    {
        LastSpawnedPowerupActor->OnDestroyed.AddDynamic(this, &APowerupSpawner::RandomizeType);
    }

    // start the respawn timer on pickup
    LastSpawnedPowerupActor->OnDestroyed.AddDynamic(this, &APowerupSpawner::StartRespawnTimer);

    // record new spawn
    LastSpawnedPowerupType = QueuedPowerupType;

    // announce spawn to subscribers
    OnPowerupSpawned.Broadcast(LastSpawnedPowerupType);


I was thinking of having it not destroy itself immediately and allowing some time for the spawner to subscribe to the powerup, but does anyone have any other ideas?

EDIT: Looked more into AActor and found that ‘IsPendingKillPending()’ is something I could check immediately afterwards.

Why can’t you handle giving player the power-up in OnComponentBeginOverlap?

The powerup actor does use OnComponentBeginOverlap to give the player the effects of the powerup. It then destroys itself since the powerup has been consumed, triggering a timer in the powerup spawner actor to spawn another powerup after a period of time. That trigger is setup by having the spawner subscribe to the powerup’s OnDestroyed event. The problem is that if someone is standing at the powerup’s spawn location at the time it spawns, the player will cause OnComponentBeginOverlap to fire which will fire OnDestroyed before the spawner can even subscribe to it.

Then don’t subscribe to it but trigger a timer from the OnComponentBeginOverlap function instead.

The powerup doesn’t know about the spawner, so it wouldn’t know what to trigger. We’re using subscriptions to avoid a hard link between the two since there isn’t really reason for the powerup to know about the spawner. At any rate, we ended up check ‘IsPendingKillPending()’ on the actor immediately afterwards to fire off the same timer as if it was subscribed.

Power-up does know about the spawner because it’s an instigator of it’s spawn(unless you’ve passed nullptr as an instigator). If you really need to do this that way, you can disable overlaps in the object by default and then enable them after you subscribe to the OnDestroyed event.

Hmm, good point. I could cast the instigator to the spawner and then call the appropriate function. Thanks!

EDIT: Instigator wouldn’t be the answer since it requires a pointer to APawn, so we went with Owner instead since that just takes a pointer to an AActor! Thanks again!