How To: Spawn Once
Sometimes an entity can only have one instance of a subentity. For example, maybe a hero can only ever have one shield. Here are some patterns you can use to make this work.
Spawn once then never again
Let's say when a hero picks up a shield powerup, they should only ever get one shield, and picking up more powerups should do nothing.
To do this, create a field to track the hero's shield entity:
pub field hero.HeroShield
When spawning, use the existential assignment operator ???= to only spawn a shield if the hero does not already have one:
Spawn powerup {
// ... more setup goes here
on BeforeCollide that {
if that.Category.Overlaps(Category:Hero) {
that.HeroShield ???= that.Subspawn shield {
// add a shield, if one does not exist yet
}
}
}
}
The ???= operator will only evaluate the right-hand side if the left-hand side does not already exist.
If the hero already has a shield, but it no longer exists (for example, because it was destroyed),
then this will spawn a new shield as expected.
You could consider using ??= instead if you want to only check if the hero has been assigned a shield entity,
and do not care about whether it exists still or not.
Replace previous spawn
Alternatively, perhaps you want to replace the shield each time the hero picks up a powerup, perhaps because a shield has a limited lifespan and you want to reset the lifespan each time the hero picks up a powerup.
Once again, create a field to track the hero's shield entity:
pub field hero.HeroShield
Now, always Expire the old shield and replace it with a new one:
Spawn powerup {
// ... more setup goes here
on BeforeCollide that {
if that.Category.Overlaps(Category:Hero) {
that.HeroShield.Expire // expire the old shield, if it exists
that.HeroShield = that.Subspawn shield {
// add a shield
}
}
}
}
This works because Expire does nothing if the entity does not exist,
so it is safe to call even if the hero does not have a shield yet.
You can also consider using Despawn instead of Expire if you want the old shield to immediately disappear
rather than the despawn happening at the end of the tick.