Trying to stop enemies from clumping together. What am I doing wrong?

Hi guys.

I think this is quite a common issue yet I haven’t found any solution. I have a couple of enemies that just follow you but I don’t want them to clump together, which they tend to do. Instead I’m trying to make them move as a flock.

In my code I simply cycle through every enemy instance to check the distance between them (I know this is far from optimal but I just want to make it work firstly). If they are too close they use transform.Translate() to push away from eachother. In my mind this would work but in reality it doesn’t.

Could someone explain why so that I can correct my fault?

Here’s my code (I believe the fault lies in the MoveToTarget function):

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

public class EnemyMovement : MonoBehaviour {

    [SerializeField]
    private int hp = 40;
    [SerializeField]
    private float speed = 5f;
    [SerializeField]
    private float rotSpeed = 90f;

    public Transform target;

    private void FixedUpdate()
    {
        if (target == null)
        {
            GameObject search = GameObject.FindGameObjectWithTag("Player");

            if (search != null)
            {
                target = search.transform;
            }
        }

        if (target == null)
        {
            return;
        }


        LookAtTarget();
        MoveToTarget();
    }

    private void LookAtTarget()
    {
        Vector3 direction = target.position - transform.position;
        direction.Normalize();
        float zAngle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
        Quaternion desiredRot = Quaternion.Euler(0, 0, zAngle);
        transform.rotation = Quaternion.RotateTowards(transform.rotation, desiredRot, rotSpeed * Time.deltaTime);
    }

    private void MoveToTarget()
    {
        transform.Translate(Vector3.right * Time.deltaTime * speed, Space.Self);

        GameObject[] objects = GameObject.FindGameObjectsWithTag("Enemy");
        foreach (var obj in objects)
        {
            if (Vector3.Distance(transform.position, obj.transform.position) < 2f && obj != gameObject)
            {
                Debug.Log("Correcting position");
                Vector3 dir = (transform.position - obj.transform.position).normalized;
                transform.Translate(dir * speed * Time.deltaTime, Space.Self);
            }
        }
    }
}

Here’s an article about Coordinated Movement. Seems to be about the exact problem you have.

I found a way to do this fairly simply, if you are using navmesh. Just child three navmesh obstacles to your enemy. Like I have in this picture below, one on each side, and one on the back. You can adjust the size of the obstacles to how close you want the enemies to get near each other.

Bear in mind, this may not work out well for a really large number of enemies. Also, I haven’t tested it extensively, but it has been working well so far.