I have created a flocking algorithm in C# for my unity project. I have tried to follow this example, but the problem is bringing everything together, and I'm failing to extrapolate. The following code is part of my desire to have a leader-following flocking system.
I have added following/seeking steering to the basic three steering subroutines (alignment, cohesion, separation), but right now the boids just flock on top of the leader and shadow him. I'd like for them to follow the leader, but also maintain separation from each other rather than just piling on each other like they're out of phase.
When the user selects a group of boids, and then selects where they should flock to, the boid closest is allocated leader and is assigned an A* path to the target. The other boids then call the flocking instead of pathing code.
void Update()
{
if (flock.Count > 0 &&
flockLeader != gameObject)
{
Flocking();
}
else
{
Movement();
}
}
private void Flocking()
{
Vector3 vector = Vector3.zero, alignment = Alignment(), cohesion = Cohesion(), separation = Separation(), following = Following();
int weightAlignment = 1, weightCohesion = 1, weightSeparation = 1, weightFollowing = 1;
NeighbourhoodWatch(); // determine neighbour boids (exclude self)
vector += (separation * weightSeparation);
vector += (alignment * weightAlignment);
vector += (cohesion * weightCohesion);
vector += (following * weightFollowing);
vector.Normalize();
if (!vector.Equals(Vector3.zero))
{
if (Vector3.Angle(vector, transform.forward) >= 1f)
{
transform.rotation = Quaternion.LookRotation(Vector3.RotateTowards(transform.forward, vector, rateOfTurn * Time.deltaTime, 0.0f));
}
else // rotate and move
{
transform.rotation = Quaternion.LookRotation(Vector3.RotateTowards(transform.forward, vector, rateOfTurn * Time.deltaTime, 0.0f));
transform.Translate(Vector3.forward * (speed * Time.deltaTime));
}
}
}
private Vector3 Alignment()
{
Vector3 vector = Vector3.zero;
if (neighbourhood.Count > 0)
{
foreach (GameObject boid in neighbourhood)
{
vector += boid.transform.forward;
}
vector /= neighbourhood.Count;
}
return vector;
}
private Vector3 Cohesion()
{
Vector3 vector = Vector3.zero;
if (neighbourhood.Count > 0)
{
foreach (GameObject boid in neighbourhood)
{
vector += boid.transform.position; // acquire centre of mass
}
vector /= neighbourhood.Count;
vector = vector - transform.position; // direction to centre of mass
}
return vector;
}
private Vector3 Separation()
{
Vector3 vector = Vector3.zero;
if (neighbourhood.Count > 0)
{
int spaceInvaders = 0;
foreach (GameObject boid in neighbourhood)
{
float proximity = Vector3.Distance(boid.transform.position, transform.position);
if (proximity <= footprint)
{
vector += boid.transform.position - transform.position;
spaceInvaders++;
}
}
if (spaceInvaders > 0)
{
vector /= spaceInvaders;
vector *= -1; // negation (invert direction)
}
}
return vector;
}
private Vector3 Following()
{
Vector3 vector = Vector3.zero;
vector = flockLeader.transform.position - transform.position;
return vector;
}
Solved
Well i have a few time trying something similar to this, if you want your units have a distance from your leader, just take the leader velocity and use that reverse vector, that reverse vector will be your units Destination, also use vector.scale if you want to ajust yourself the separation distance.
No comments:
Post a Comment