1. Bird swarm behavior, three forces as the focus
The birds move in one direction and give them a target in the game, and when they fly toward the target, if the code simply lets the birds move toward the target and then moves forward, it can cause the birds to crowd, especially after reaching the target point where the birds flock together.
The effect we want to achieve is:
1. Birds do not gather together (separation force)
2. Birds are not the same in the direction of each individual, but the overall direction is to move to the target point (Team Lieli)
3. Individual birds are not too far from the big team (gathering force)
and some other behavior .
Since it is force to influence speed, it is necessary to use Newton's second law: F=ma here m is our own definition of size and does not change, so F is proportional to a. Three forces are divided, and the ultimate influence on the birds is the resultant force of the three forces.
2. Separation Force
Public Vector3 velocity=vector3.forward;//Current speed public
Vector3 sumforce=vector3.zero;//resultant force public
float m = 1;/ /Quality public
list<gameobject> separationneighbors = new list<gameobject> ()//To store a game object in scope that requires a function of separation force Public
float separationdistion=3;//Separation Force inspection range Public
Vector3 separationforce=vector3.zero;//separation Force
public float Separationweight = weight of 1;//separation force
The separation force is determined by the distance between itself and the surrounding bird, and the direction is in the opposite direction to the other birds.
First, check out a certain range of birds which
collider[] colliders = Physics.overlapsphere (transform.position, separationdistion);//The first argument is the center of the ball, and the second parameter is the radius of the shot. Return all collider to the collision
///will get all collider game objects into the list
foreach (collider C in colliders)
{
if (c!= null & & C.gameobject!= This.gameobject)
{
separationneighbors.add (c.gameobject);
}
}
After acquiring the bird around itself, the smaller the distance between each bird and itself, the greater the separation force, the direction of which is the detected bird pointing to the bird.
All objects in the list give Thisgameobject a force
foreach (gameobject neighbor in separationneighbors)
{
Vector3 dir = transform.position-neighbor.transform.position;//here is a vector, from the target bird point to the bird, length of two birds distance
Separationforce + = Dir.normalized/dir.magnitude;//dir.normalized is to normalized the direction (that is, the direction is constant, the length becomes 1), the dir.magnitude is to get the length of the vector
}
// The separation force changes the joint
if (Separationneighbors.count > 0)
{
separationforce *= separationweight;
Sumforce + + Separationforce;
}
3. Queue Force
Public list<gameobject> alignmentneighbors = new list<gameobject> ()//The game object used to store the queue force used in the range is public
Float alignmentdistance = Check range of 6;//queue Force public
Vector3 aligmentforce=vector3.zero;//Queue Force public
float Alignmentweight = weight of 1;//queue force
Again, first check the birds around the bird, but the scope of this check needs to be larger.
colliders = Physics.overlapsphere (transform.position, alignmentdistance);
foreach (collider C in colliders)
{
if (c.gameobject!= null && c.gameobject!=)
{this.gameobject />alignmentneighbors.add (C.gameobject);
}
and calculate the overall direction of the nearby birds.
Vector3 avgdir=vector3.zero;//stores the average direction of all neighbors
foreach (Gameobject neighber in alignmentneighbors)
{
Avgdir + = neighber.transform.forward;//Add all the neighbors ' directions.
And this bird needs to adjust to the general direction, it is the vector of knowledge-vector a minus vector b to get a vector from B to point A. (the average of the vector in the direction of the nearby bird) minus the direction of the bird, the longer the vector gets, the greater the separation force.
if (Alignmentneighbors.count > 0)
{
Avgdir/= alignmentneighbors.count;//average direction
Aligmentforce = avgdir-transform.forward;//calculates the queue force (vector knowledge)
aligmentforce *= alignmentweight;
Sumforce + + Aligmentforce;
}
4. Aggregation Force
Public Vector3 cohesionforce=vector3.zero;//Aggregation Force public
float cohesionweight = 1;//weight
The aggregation force can be directly used to check the range of the queue force, the same use of vector knowledge to obtain the center of the nearby birds-the direction vector of nearby birds divided by the number of nearby birds, is the center point, we let the bird force to the center point near
Aggregation force if
(alignmentneighbors.count <= 0) return;//If there are no neighbors nearby
Vector3 center = vector3.zero;//All Neighbors ' central point
foreach (gameobject n in alignmentneighbors)
{
Center = n.transform.position;
}
Center/= Alignmentneighbors.count;
Vector3 dirtocenter = center-transform.position;//A vector from this point to the center point, the vector length can be used as the size of the strength
cohesionforce + = Dirtocenter;
Sumforce + = Cohesionforce;
5. Final effect
The effect of each force is very bad, but after use, the effect can be qualitative change. Do some other processing, such as setting an endpoint called Target, so that all the birds animation start playing a different point of time, it will not appear monotonous. Next post the full code:
Using Unityengine;
Using System.Collections;
Using System.Collections.Generic;
public class Crowai:monobehaviour {public gameobject target;//Bird Group target public float targetweight = 1;//Target Force weight
Public Vector3 velocity=vector3.forward;//Current speed public Vector3 sumforce=vector3.zero;//resultant force public float m = 1;//quality Public list<gameobject> separationneighbors = new list<gameobject> ()//is used to store objects in the scope that need to be decoupled. Public Flo At separationdistion=3;//separation Force Inspection range Public Vector3 separationforce=vector3.zero;//separation Force public float separationweight =
1;//the weight of the separation force public list<gameobject> alignmentneighbors = new list<gameobject> ()//to store the range of game objects that require the queue force public float alignmentdistance = Check range of 6;//queue Force public Vector3 aligmentforce=vector3.zero;//Queue Force public float ALIGNM
Entweight = 1;//The weight of the queue force public Vector3 cohesionforce=vector3.zero;//Aggregation Force public float cohesionweight = 1;//weight Public float checkinterval=0.2f;//Check time interval private Animation animation;//Flying Animation//Use this for initialization void Start () {invokerepeating ("Calcforce", 0, Checkinterva L)//from 0 seconds after every checkinterval seconds to execute the Calcforce method animation = getcomponentinchildren<animation> ();//Get animation in
Voke ("Playeranim", Random.range (0, 2f));//Play animation at different times///<summary>///play animation///</summary> void Playeranim () {animation.
Play ();
} void Calcforce () {sumforce = Vector3.zero;
Separationforce = vector3.zero;//separation force Aligmentforce = vector3.zero;//queue force Cohesionforce = vector3.zero;//Aggregation Force
Separationneighbors.clear ();
Alignmentneighbors.clear (); collider[] colliders = Physics.overlapsphere (transform.position, separationdistion);//The first argument is the center of the ball, and the second parameter is the radius of the shot. Return all collider to the collision///will get all collider game objects into the list foreach (Collider C in colliders) {if (c
!= null && c.gameobject!= this.gameobject) { Separationneighbors.add (C.gameobject);
}//List all objects to thisgameobject a force foreach (Gameobject neighbor in separationneighbors) {
Vector3 dir = transform.position-neighbor.transform.position;
Separationforce + = Dir.normalized/dir.magnitude; }//Separation force change Joint if (Separationneighbors.count > 0) {separationforce *= Separationweigh
T
Sumforce + = Separationforce;
} colliders = Physics.overlapsphere (transform.position, alignmentdistance); foreach (collider C in colliders) {if (C.gameobject!= null && c.gameobject!= THIS.GAMEOBJEC
T) {Alignmentneighbors.add (c.gameobject);
} Vector3 avgdir=vector3.zero;//Store the average direction of all neighbors foreach (Gameobject neighber in alignmentneighbors) {Avgdir + = neighber.transform.forward;//Adds all the neighbors ' directions.
} if (Alignmentneighbors.count > 0) {avgdir/= alignmentneighbors.count;//average direction
Aligmentforce = avgdir-transform.forward;//Calculates the queue force (vector knowledge) Aligmentforce *= alignmentweight;
Sumforce + = Aligmentforce; }//Aggregation force if (alignmentneighbors.count <= 0) return;//return Vector3 Center = vector3.z If there are no neighbors nearby
ero;//all Neighbors ' central point foreach (gameobject n in alignmentneighbors) {center = n.transform.position;
Center/= Alignmentneighbors.count;
Vector3 dirtocenter = center-transform.position;//A vector from this point to the center point, the vector length can be used as the size of the strength cohesionforce + = Dirtocenter;
Sumforce + = Cohesionforce;
target = Gameobject.find ("target"). Gameobject; Vector3 TargetDir = target.transform.position-transform.position;//Get this point to the vector Sumforce = = (Targetdir.normali Zed-transform.forward) * Targetweight//The location of the target affects the resultant force}//UpdatE is called once per frame void Update () {Vector3 a = sumforce/m;//acceleration velocity = A * time.deltat
Ime Let the crow's direction with the speed of the same direction, so that different speed direction will appear all kinds of changes, parameter one: this orientation; parameter two: This needs to be changed into direction, slowly changing towards transform.rotation = Quaternion.slerp (trans
Form.rotation, quaternion.lookrotation (velocity), time.deltatime); Transform.
Translate (Velocity * time.deltatime, space.world); }
}