Multiple spawns

Cheers !

I’ve been trying for some time to include several spawn locations in my prototype (each having the same destination but a different starting point).

I tried to duplicate the “ObjectPool” prefab, but since the Gridmanager script is a singleton, when calculating the path(s), it doesn’t work as intended. I’m struggling to see the best way to approach this problem, if you have any leads I’m all ears! <3

Hi Hyunk,

I think you identified the problem correctly. In the Pathfinder, we defined “the” startCoordinates. And in the EnemyMover class, we execute coordinates = pathfinder.StartCoordinates;.

Unity does not know anything about your other start coordinates yet. And the enemies do not know what their respective starting coordinates are. This is something you will have to implement in your code.

A little hint: There is no need for multiple GridManager or Pathfinder objects.

Good luck! :slight_smile:


See also:

1 Like

Ok, I think you gave me an idea, it might be enough to make sure that each enemy knows his initial position, I’ll dig in this direction. ! Thank you for your quick and precise answer Nina,it looks so obvious to you :sweat_smile:

I struggled a lot because I had modified the original code too much, while the solution was not so complicated. For those interested, here is the list of modifications needed to the original code to allow multiple spawn points:

[EDIT : Actually this solution is clearly not optimized nor maintainable (see Nina’s answer below)]

  • Place as many “ObjectPool” gameobject as needed in the scene (one for each spawn point)

  • In the EnemyMover script, in Awake(), replace pathfinder=FindObjectOfType<Pathfinder>(); by GetComponentInParent<Pathfinder>();

    because there are now several Pathfinder

  • In the Tile script, modify the variable “Pathfinder pathfinder;” by “Pathfinder[] pathfinders

    then declare it with pathfinders = FindObjectsOfType<Pathfinder>(); in Awake()

  • In the same script, Modify OnMouseDown() by wrapping its contents in a foreach loop:

foreach(Pathfinder pathfinder in pathfinders)
        { ..... }

In the pathfinder script, it is now necessary to recalculate the path of each enemy in each ObjectPool each time a tower is placed. It’s this part that I’m not sure if it’s relevant, but it seems to work:

  • Create an object containing all the ObjectPools in the scene (I called it PoolManager)

  • Create a script on this object (I called it Broadcaster)
    whose body is:

public class Broadcaster: MonoBehaviour
{
    public void NotifyAllReceivers()
    {
        BroadcastMessage("RecalculatePath", false, SendMessageOptions.DontRequireReceiver);
    }
}
  • And finally, in Pathfinder, we need a reference to our Broadcaster :

Broadcaster broadcaster
.
.
.
broadcaster = GetComponentInParent<Broadcaster>();

then modify the “NotifyReceivers()” method:

public void NotifyReceivers()
{
    broadcaster.NotifyAllReceivers();
}

I think that’s all :slight_smile: And thank you again Nina!

The object pool part makes sense. I assume the Hierarchy is like this?

ObjectPools (root)
> ObjectPool
>> Enemy
>> Enemy
>> Enemy
> ObjectPool
>> Enemy
> ObjectPool
>> Enemy
>> Enemy

This means there are 3 ObjectPool game objects parented to ObjectPools (root). And the ObjectPool game objects have got children.

Is the PoolManager assigned to the root game object?

There are several questions you’ll have to answer to find a solution for your problem:

  • What exactly is the role of an ObjectPool object?
  • What exactly is the purpose of a Pathfinder object?
  • What exactly is the purpose of an EnemyMover object?
  • Whose Recalculate method is supposed to get called in which case? (Are all Recalculate path methods supposed to be called? Or just a subset of them?)

If you know exactly how the objects are supposed to interact with one another in which case, you will be able to make your idea work. The implementation is simple because you know everything you need: classes, objects, methods, arrays, if-statements.


You do not have to use Gary’s solution if it makes implementing your ideas difficult. Gary’s solution solves Gary’s problems.

Get rid of the Broadcaster (BroadcastMessage). It is not only very slow but you also cannot “see” what happens here. Since you have the reference to all Pathfinder objects, you could recalculate the path by calling the RecalculatePath method on them.


A potential concept

Each Pathfinder object contains a valid path (pool.path), which is associated with one ObjectPool object. Each Enemy object has got its own path (enemy.path). When a new enemy gets spawned, the pool.path gets assigned to its enemy.path. No new calculations.

When a new tower is supposed to get spawned, each Pathfinder checks the assumed tower.coordinates with the coordinates in its pool.path. No calculation here. If the tower.coordinates are not in the pool.path, there is no need to recalculate anything.

If the tower.coordinates are in the pool.path, you recalculate the pool.path. If the new pool.path is valid, you have to ensure that your enemies have got valid paths too. You have multiple options:
a) You recalculate an individual enemy.path for all enemies. (Worst performance but it covers all cases)
b) You recalculate an individual enemy.path for all enemies whose path is about to be blocked by the tower. (Better performance than a))
c) You recalculate an individual enemy.path for all enemies whose path is about to be blocked by the tower. And the recalculated path is just a path to the closest waypoint of the new pool.path.
d) You analyse the situation and try to figure out which paths or parts of paths need to be recalculated to make your game not only performant but also look/feel good.

No tower if one of the enemy gets an invalid path. Then the enemy continues using its enemy.path. In that case, you don’t want to recalculate the enemy.path but reuse the original data.

1 Like

I suspected that I was not going in the right direction with my approach, and even if it works (for the moment), the slightest modification could prove to be tedious… I will completely review my code following your advice . :face_with_monocle:

I clearly relied too heavily on the tutorial’s solution for a problem I thought was rather similar.

Once again, thank you for all your precious help Nina. :four_leaf_clover:

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms