- Home /
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);
}
}
}
}
private void LookAtTarget()
{
Vector3 direction = target.position - transform.position;
direction.Normalize();
float zAngle = $$anonymous$$athf.Atan2(direction.y, direction.x) * $$anonymous$$athf.Rad2Deg;
Quaternion desiredRot = Quaternion.Euler(0, 0, zAngle);
transform.rotation = Quaternion.RotateTowards(transform.rotation, desiredRot, rotSpeed * Time.deltaTime);
}
Could just be
private void LookAtTarget()
{
var desiredRot = Quaternion.LookRotation(
Vector3.up,
target.position - transform.position);
transform.rotation = Quaternion.RotateTowards(
transform.rotation,
desiredRot,
rotSpeed * Time.deltaTime);
}
Now the problem with your code might be that the need to move closer to the player is stronger than the local constraints you add to your flock. Only the enemies on the outside of the flock can actually move away.
If ins$$anonymous$$d you used an OverlapCircle to detect every enemy in some range, and that you moved away from their center of gravity, you would probably get a better result.
Better yet, if you used navmesh agents, you would get both pathfinding and collision avoidance.
Answer by Zodiarc · Oct 03, 2018 at 08:10 AM
Here's an article about Coordinated Movement. Seems to be about the exact problem you have.
Read that article and some other ones from that site. Really great one however they focused more on moving a unit like in a strategy game which was not what I was looking for (I was a bit unclear). I have ins$$anonymous$$d made use of my objects rigidbodies making them dynamic and adding a repel force between them when they get too close. Thanks for the answer through.
Please your new script. I am having the same problem and have been trying
If you are using navmesh, I found a way that doesn't require scripting, I posted it as a reply on this forum. It basically involves adding 3 navmesh obstacles as children to the enemy object. I just used regular cubes, added the navmeshobstacle components to them, and then once I had them all in place around the enemy, I removed the mesh render and box collider components from them.
Answer by zombievirals · Dec 05, 2019 at 11:56 PM
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.
Your answer
![](https://koobas.hobune.stream/wayback/20220612175701im_/https://answers.unity.com/themes/thub/images/avi.jpg)
Follow this Question
Related Questions
Making a bubble level (not a game but work tool) 1 Answer
Multiple Cars not working 1 Answer
Lag at first second of transform.Translate movement 2 Answers
Distribute terrain in zones 3 Answers
Enemy Movement Problem! 1 Answer