my enemys are piling up with vector2.move towards,

hi there thanks for taking the time to look at my question im currenty making a 2D side scroller/platformer and im currently facing a issue where my enemies are piling up on top of each other. through googling i see alot of Astar pathfinding solving this however i hesitant to jump into ai right now as i glanced over its internal scripts and they are outside my current knowledge and im still attempting to get a understanding of just using scripting to achieve what i want.

i currently have my enemies correctly chasing my player with a vector2.movetowards however eventually they all pile on each other.

through google i have found this is a typical outcome of movetowards and i found this solution Stop enemies from grouping up - Questions & Answers - Unity Discussions and i implemented its code

void avoidOthers()
        {
            var hits = Physics2D.OverlapCircleAll(enemy.transform.position, avoidenceRadius);//create a circle around each enemy and check to see if they are not colliding
            foreach (var hit in hits)
            {
                if(hit.GetComponent<DartFish>() != null && hit.transform != transform)//check to see if it is a enemy
                {
                    Debug.Log("enemy transform" + enemy.transform.position);
                    Debug.Log("hit transform" + hit.transform.position);
                    Vector2 difference = enemy.transform.position - hit.transform.position;//check how close we are to another enemy
                    difference = difference.normalized / Mathf.Abs(difference.magnitude);//calculate how long the vector is
                    sum += difference;//add together differences so we can calculate a average of the group
                    count++;
                }
            }
            if(count > 0)// if we found enemys interfearing with each other
            {
                sum /= count;//average of the movement
                sum = sum.normalized * avoidenceSpeed;//calculate movement speed
                Debug.Log("sum = " + sum);
                enemy.transform.position = Vector2.MoveTowards(enemy.transform.position, enemy.transform.position + (Vector3)sum, avoidenceSpeed * Time.deltaTime);
            }
     
        }

however i needed to add “enemy” to each transform.position or they would instantly snap from my spawn location to the player. after adding enemy they stopped snapping over a large distance except now they started piling again

all of my debug logs look like they are printing out the correct values

i was also reading through transform.translate as looking at my “sum” values this should be how much they are moving away from each other

so i changed the line

enemy.transform.position = Vector2.MoveTowards(enemy.transform.position, enemy.transform.position + (Vector3)sum, avoidenceSpeed * Time.deltaTime);

to

transform.Translate((Vector3)sum * avoidenceSpeed * Time.deltaTime, Space.World);

now it seems to only effect one fish and the others clump together still
from my understanding physics.overlapcircle all should be functioning as a list?

i also noticed that my one enemy that was using the avoidence method was still moving towards my player so i then added a bool to block my chaseme() method

 if(count > 0)// if we found enemys interfearing with each other
        {
            sum /= count;//average of the movement
            sum = sum.normalized * avoidenceSpeed;//calculate movement speed
            Debug.Log("sum = " + sum);

            if(sum != Vector2.zero)
            {
            weHitAnotherFish = true;
            transform.Translate((Vector3)sum * avoidenceSpeed * Time.deltaTime, Space.World);
            sum = Vector2.zero;//zero the sum in preperation for the next contact
            }
            else
            {
                weHitAnotherFish = false;
            }
        }

heres my entire code albeit long and possibly repetitive(small changes such as jus adding a -)(still relatively new to coding)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class DartFish : MonoBehaviour
{
    public Transform target;
    
    public float movementSpeed;
    private float initialMovementSpeed;
    public float dashSpeed;
    private float spawnSpeed = 1.5f;
    public float chaseRadius;
    private float initialChaseRadius;
    public float dashRadius;
    private Vector2 targetDirection;
    private float directionX;
    private float previousDirectionX;
    private float directionY;
    private float spriteAngle;
    private float previousAngle;
    private float currentSpriteAngle;
    private float difference;
    private SpriteRenderer mySpriteRenderer;
    private Rigidbody2D myRigidbody;
    private bool directionIsAboutToChange;
    private bool directionHasChanged;
    private Vector3 angleCompensation;
    // avoid others variables
    public float avoidenceSpeed;
    public float avoidenceRadius;
    public Transform enemy;
    private Vector2 sum = Vector2.zero;
    private float count;
    public bool weHitAnotherFish;

    

    // Start is called before the first frame update
    void Start()
    {
        enemy = GameObject.FindWithTag("dartfish").transform;
        target = GameObject.FindWithTag("Player").transform;
        mySpriteRenderer = GetComponent<SpriteRenderer>();
        myRigidbody = GetComponent<Rigidbody2D>();
        initialMovementSpeed = movementSpeed;
        initialChaseRadius = chaseRadius;
    }

    // Update is called once per frame
    void Update()
    {
        targetDirection = target.position - transform.position;// where is the player?
        directionX = targetDirection.x;//extract only x for "check direction"
        directionY = targetDirection.y;
        if(directionX < -initialChaseRadius + .5f)// is the player further then the chase radius?
        {
            myRigidbody.velocity = new Vector2(-1.5f, 0);
        }
        else
        {
            myRigidbody.velocity = Vector2.zero;
        }
        if(directionX > 0)//calculate tangent angle to the player in radians and then convert it to degrees
        {
            spriteAngle = Mathf.Atan2(targetDirection.y, targetDirection.x) * Mathf.Rad2Deg;   
        }
        else if(directionX < 0)//if player is to the left flip opp/adj and add 100° to zero angle
        {
            spriteAngle = Mathf.Atan2(targetDirection.x, targetDirection.y) * Mathf.Rad2Deg +100f;
        }
        currentSpriteAngle = spriteAngle;
        difference = spriteAngle - previousAngle;
        difference = Mathf.Abs(difference);
        if(directionX < 1 && directionX > -1)//are we about to change directions?
        {
            //Debug.Log("direction is about to change");
            directionIsAboutToChange = true;
        }
        if(directionIsAboutToChange == true)//did we pass through trigger zone?
        {
            if(directionX > 1 || directionX < -1)
            //Debug.Log("direction has changed");
            directionHasChanged = true;
        }
        lookAtMe();
        avoidOthers();
        chaseMe();
        
    /*
        //debug logs with spam control
        if(previousAngle != spriteAngle)
        {
        Debug.Log("angle = " + spriteAngle);
        }
        if(difference != 0)
        {
        Debug.Log("difference = " + difference);
        }
        if(previousDirectionX != directionX)
        {
        Debug.Log("directionX = " + directionX);
        }
        if(previousAngle != currentSpriteAngle)
        {
        Debug.Log("previous angle = " + previousAngle);
        }
        */
        previousAngle = currentSpriteAngle;
        previousDirectionX = directionX;
    }

    void lookAtMe()
    {
        if(directionHasChanged == true)//angle compensation for sprite flip
        {
            if(directionY > 0)//is the player above or below us
            {
                angleCompensation = transform.localEulerAngles;//get current rotation
                //flip it
                if(directionX > 0)
                {
                transform.localEulerAngles = -angleCompensation;   
                }
                if(directionX < 0)
                {
                transform.localEulerAngles = angleCompensation;    
                }   
            }
            if(directionY < 0)
            {
                if(directionX > 0)
                {
                transform.localEulerAngles = angleCompensation;   
                }
                if(directionX < 0)
                {
                transform.localEulerAngles = -angleCompensation;    
                }    
            }
            
            directionHasChanged = false;
            directionIsAboutToChange = false;
        }
        if(directionX < -1)
        {
            mySpriteRenderer.flipX = true;
            //Debug.Log("entered void lookAtMe.directionX <");
            if(spriteAngle > previousAngle && spriteAngle < 50f )
            {
            transform.Rotate(0f, 0f, -difference);
            }
            else if(spriteAngle < previousAngle && spriteAngle > -50f)
            {
            transform.Rotate(0f, 0f, difference);
            }
        }
        else if(directionX > 1)
        {
            mySpriteRenderer.flipX = false;
            //Debug.Log("entered void lookAtMe.directionX >");
            if(spriteAngle > previousAngle && spriteAngle < 50f)
            {
            transform.Rotate(0f, 0f, difference);
            }
            else if(spriteAngle < previousAngle && spriteAngle > -50f)
            {
            transform.Rotate(0f, 0f, -difference);
            }  
        }
    }

    void avoidOthers()
    {
        var hits = Physics2D.OverlapCircleAll(enemy.transform.position, avoidenceRadius);//create a circle around each enemy and check to see if they are not colliding
        foreach (var hit in hits)
        {
            if(hit.GetComponent<DartFish>() != null && hit.transform != transform )//check to see if it is a enemy
            {
                Debug.Log("enemy transform" + enemy.transform.position);
                Debug.Log("hit transform" + hit.transform.position);
                Vector2 difference = enemy.transform.position - hit.transform.position;//check how close we are to another enemy
                difference = difference.normalized / Mathf.Abs(difference.magnitude);//calculate how long the vector is
                sum += difference;//add together differences so we can calculate a average of the group 
                count++;
            }
        }
        if(count > 0)// if we found enemys interfearing with each other
        {
            sum /= count;//average of the movement
            sum = sum.normalized * avoidenceSpeed;//calculate movement speed
            Debug.Log("sum = " + sum);

            if(sum != Vector2.zero)
            {
            weHitAnotherFish = true;
            transform.Translate((Vector3)sum * avoidenceSpeed * Time.deltaTime, Space.World);
            sum = Vector2.zero;//zero the sum in preperation for the next contact
            }
            else
            {
                weHitAnotherFish = false;
            }
        }

    }

    void chaseMe()
    {        
    if(Vector3.Distance(target.position, transform.position) <= chaseRadius && Vector3.Distance(target.position, transform.position) > dashRadius && weHitAnotherFish != true)
        {
        transform.position = Vector3.MoveTowards(transform.position, target.position, movementSpeed * Time.deltaTime);
        }
    else if(Vector3.Distance(target.position, transform.position) <= dashRadius && weHitAnotherFish != true)
        {
            transform.position = Vector3.MoveTowards(transform.position, target.position, dashSpeed * Time.deltaTime);
        }    
    }
}

,

By piling up, do you mean all of them are occupying roughly the same space (such as all on 0,0 coordinates?) Or do you mean they are all in their own space/coordinates/position but are touching each other trying to get to the player?

Do the enemies have a boxCollider2D or CircleCollider2D WITHOUT the ‘isTrigger’ checked?

So you could have two colliders on the same enemy game object. One (box, circle, whatever type) with ‘isTrigger’ checked to see if the enemy hit a trigger (if that is even needed). Another (box, circle, whatever type) with ‘isTrigger’ unchecked for main collision.

If the enemies have colliders with ‘isTrigger’ unchecked, then they should collide instead of piling up on one another in one coordinate/position. Theoretically, you shouldn’t need the ‘avoidOthers()’ method.

If you can answer me the above questions and confirm your collider situation, I can dig deeper.