 # AI: Flocking

See all my AI projects HERE

Flocking should contain at least three steering behaviors that individually describes how an actor behaves base on its neighbors’ velocity and position.

Seperation: Actor should steer away from all neighbors. The closer a neighbor is, the harder the actor should steer away from it. Seperation describes the sum of all such steer away behavior. ```private Vector2 Separation(){
Vector2 separation = Vector2.zero ;
foreach (IActor actor in GetNeighborActors()) {
Vector2 posDiff = actor.Position - _actor.Position;
float T = 1.0f - (posDiff.magnitude / neighborDistance);
separation += -posDiff * T * T;
}
separation = (GetNeighborActors ().Count != 0) ? separation : Vector2.zero;
return separation;
}
```

Alignment: Actor should steer towards the direction of the average speed of all neighbors. ```private Vector2 Alignment(){
Vector2 alignment= Vector2.zero ;
foreach (IActor actor in GetNeighborActors()) {
alignment += actor.Velocity.normalized;
}

alignment = (GetNeighborActors ().Count !=0) ? alignment / GetNeighborActors ().Count - _actor.Velocity.normalized: Vector2.zero ;
return alignment;
}
```

Cohesion: Actor should steer towards the average position of all neighbors. ```private Vector2 Cohesion(){
Vector2 cohesion= Vector2.zero ;
Vector2 avPos = Vector2.zero ;
foreach (IActor actor in GetNeighborActors()) {
avPos += actor.Position;
}
avPos = avPos / GetNeighborActors ().Count;
cohesion = (GetNeighborActors ().Count !=0) ? avPos - _actor.Position : Vector2 .zero;
return cohesion;
}
```

Flocking is simply the combination of the three.

```flocking = Separation() * separationWeight + Alignment()* alignmentWeight + Cohesion()* cohesionWeight;

_actor.SetInput( flocking.x, flocking.y );
```

To define all neighbors, it is better to leave out the ones at the back of the actors. In real life, flocking birds can’t really see those behind them. Thus we can use a neighbor distance and an angle to define the area of neighbors.

```private List<IActor> GetNeighborActors(){
List<IActor> neighbor = new List<IActor>() ;
foreach (IActor actor in Flocking.allActors) {
if ((actor.Position  - _actor.Position).magnitude < neighborDistance) {
}
if ((new Vector2 (actor.Position.x,actor.Position.y)  - _actor.Position).magnitude > neighborDistance) {
neighbor.Remove(actor);
}
if (Vector2.Angle ((actor.Position - _actor.Position), _actor.Velocity) > NEIGHBORANGLE && Mathf.PI * 2.0f - NEIGHBORANGLE > Vector2.Angle ((actor.Position - _actor.Position), _actor.Velocity)) {
neighbor.Remove (actor);
}
if (neighbor.Contains(_actor)){
neighbor.Remove(_actor);
}
}
return neighbor;
}
```

I added a button to toggle the flocking behavior, and used a few line renderer to show the neighbor area. I also have three sliders to control the weights of the three component of flocking. Finally, I added a pursuer that chases anything nearby, and the flocking actors also evades from the pursuer while flocking. It looks like this: 