- Home /
Units merge into each other with pathfinding
Hey Guys, Its a 3d rts and I have posted the code below. The code gets a list of all the units on the map and draws a ray between them. It then calculates the distance between each unit. When the unit distance is less than 1.5 it repels the units by the vector given by the difference in their direction. Sometimes when three units are grouped and traveling together two of the units will merge together and i dont know why. I tihnk it has to do with opposing forces and them being too close to each other. Let me know if you guys have any ideas or suggestions! Thanks!!
public void LocalAvoidance(){ //do the distance of specific vectors like x,z to determine direction unit is pushed back
//get drawn ray between all units
for (int i=0; i<UnitsList.Count; i++) { //this iterates through my list of unit objects
for(int y=0; y<UnitsList.Count; y++){ //this iterates again through the list to make sure we capture all objects
Debug.DrawRay (UnitsList[i].transform.position, UnitsList[y].transform.position - UnitsList[i].transform.position);
//this draws a ray from unit to unit
float distance = Vector3.Distance (UnitsList[i].transform.position, UnitsList[y].transform.position);
//this calculates the distance from one unit to another
if (distance <= 1.5) { //if the distance is less than 1.5 push the unit away
Vector3 direction = Vector3.zero; //creates zero vector
direction =UnitsList[i].transform.position - UnitsList[y].transform.position; //gets the direction vector
direction.y=0;//try to make it so units dont bounce up
transform.Translate(-direction*5*Time.deltaTime); //pushing in the opposite direction of the movement.
}
}
}
}
Answer by morethan3 · May 09, 2014 at 08:38 AM
What I think you what to do is move each object away from the average position of all near objects.
So you would move it in the direction of the green arrow.
However, for a scenario like this:
You probably don't want to move the blue object, just all of the red ones.
Try the function below and see if that fixes it:
public void LocalAvoidance(){ //do the distance of specific vectors like x,z to determine direction unit is pushed back
//get drawn ray between all units
for (int i=0; i<UnitsList.Count; i++) { //this iterates through my list of unit objects
List<Vector3> nearUnits = new List<Vector3>();
for(int y=0; y<UnitsList.Count; y++){ //this iterates again through the list to make sure we capture all objects
Debug.DrawRay (UnitsList[i].transform.position, UnitsList[y].transform.position - UnitsList[i].transform.position);
//this draws a ray from unit to unit
Vector3 offset = UnitsList[y].transform.position - UnitsList[i].transform.position;
float sqrLen = offset.sqrMagnitude;
//2.25 is 1.5^2
// Comparing distances this way is faster than using the distance function.
if (sqrLen <= 2.25) { //if the distance is less than 1.5 push the unit away
nearUnits.add(UnitsList[y].transform.position);
}
}
// Calculate the average position of nearby units here
Vector3 tempPos = Vector3.zero;
foreach(Vector3 unit in nearUnits) {
tempPos += unit;
}
tempPos /= nearUnits.Length;
Vector3 offset = tempPos - UnitsList[i].transform.position;
//If you do want to avoid scenrio 2 show above do the following
//otherwise just use the code inside the if statement
float sqrLen = offset.sqrMagnitude;
// I've just used a distance of 0.2 here you might want to play with this
if (sqrLen > 0.2 * 0.2) {
offset.y = 0; //try to make it so units dont bounce up
transform.Translate(offset * 5 * Time.deltaTime); // It shouldn't need to be minus since I've already calculated the oppsite vector.
}
}
}
@morethan3 I found the answer to my question. I just needed to call the list index for my translation, UnitsList[i].transform.translate.etc, but i didnt know the square of the magnitude is faster than the distance. Your code may be useful then and I will try to implement to see what happens. Thanks for helping me man!