Loop for managing enemies gone wrong?

I made my EnemyMover script a script that isnt part of my enemy prefab. Instead, it picks them up from the object pool and then moves them in a complex loop as shown below :

IEnumerator MoveEnemyToWaypoint()
{

    for (int i = 0; i < path.Count; i++)
    {
        foreach (GameObject enemy in _enemies)
        {

            if (i == 0)
            {
                enemy.transform.position = path[0].transform.position;
            }

            var enemyCurrentPos = enemy.transform.position;

            Vector3 startPosition = enemyCurrentPos;

            if (i + 1 < path.Count)
            {
                Vector3 endPosition = path[i + 1].transform.position;

                float travelPercent = 0f;

                enemy.transform.LookAt(endPosition);

                while (travelPercent < 1f)
                {
                    travelPercent += Time.deltaTime;

                    enemy.transform.position = Vector3.Lerp(startPosition, endPosition, travelPercent);

                    yield return new WaitForEndOfFrame();
                }

                enemyCurrentPos = endPosition;
            }
        }
    }
    for (int d = 0; d < _enemies.Count; d++)
    {
        Destroy(_enemies[d]);
    }
}

The problem I encounter is when my loop has more than one enemy to manage. It starts moving them one by one instead of all moving them independently at the same time like I hoped to. So my question is : is there a way to achieve this desired result this way? What modifications could help? Or if I should stick to how its shown in this class?

I wanted to upload two videos here I took to show the comparison between a single enemy or multiples but I cant, so basically with a single enemy just imagine that it moves just like in this class, smoothely until end of path.

With multiples, one will move to the next waypoint, then the other will do the same, etc. Like they’re all waiting for eachother before going for the next waypoint. I know this behaviour makes sense in a loop but I’m still asking to know if there’s a way to do it similar to this but have them all move at the same time.

Thank you.

Hi Zodi,

It’s great to see that you are challenging yourself. :slight_smile:

What exactly do you mean by that? Even if the code is able to move the enemies independently, it will have to move the single enemies one by one.

Since you have a logic flow in mind, reenact the actual logic flow of your code with Debug.Logs. Maybe your code does not do what you think it does.

A potential issue could be the for-loop. While the foreach-loop selects the enemies one by one, the i is independent of anything but the loop. If i == 0, all enemies get set to path[0].transform.position;. path[i + 1].transform.position might not be the position your enemy is supposed to move to according to your idea.

I hope this helped you a bit. :slight_smile:

Hello Nina, is there a way I could send short videos to show what I mean? Im having a hard time explaining it and I feel like it would be a lot clearer that way

This is exactly what I dont like, because unlike when there’s just one, now they all stop at each waypoints as the loop goes through the other enemies.

Your code is moving the enemies one by one. It moves one enemy from one waypoint to the next. Only when that enemy reaches the waypoint does it move on to the next enemy.

Batch moving the enemies like this is not ideal, but let’s try and fix your coroutine.

If you make your path loop go to i < path.Count - 1 you don’t need the if (i + 1 < path.Count) check because i + 1 will always be less than path.Count.

You can probably just switch the foreach(GameObject enemy in _enemies) line with the while travelPercent < 1f) line. This will then slice the travel time first, and then give each enemy a chance to travel that slice before doing it again. You would have to move a few variables around because your travelPercent initialisation is inside the loop and will now be required earlier. It’s a simple change, really

IEnumerator MoveEnemyToWaypoint()
{
    for (int i = 0; i < path.Count - 1; i++)
    {
        float travelPercent = 0f;

        while (travelPercent < 1f)
        {
            travelPercent += Time.deltaTime;
            
            foreach (GameObject enemy in _enemies)
            {
                if (i == 0)
                {
                    enemy.transform.position = path[0].transform.position;
                }

                var enemyCurrentPos = enemy.transform.position;

                Vector3 startPosition = enemyCurrentPos;

                Vector3 endPosition = path[i + 1].transform.position;

                enemy.transform.LookAt(endPosition);

                enemy.transform.position = Vector3.Lerp(startPosition, endPosition, travelPercent);
            }

            yield return new WaitForEndOfFrame();
        }
    }
    for (int d = 0; d < _enemies.Count; d++)
    {
        Destroy(_enemies[d]);
    }
}

Apart from changing the i < path.Count and removing enemyCurrentPos = endPosition I did nothing more than rearranged the code

Also, your enemies are going to move at different speeds. The farther the waypoints are from each other, the quicker the enemies will move. This is because they want to move from waypoint a to waypoint b in 1 second. Regardless of how far they are apart.

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

Privacy & Terms