A realistic, natural-looking, flocking behavior (for example birds or antelopes or bats) can be created through creating collections of objects with the following four simple rules:
Each member of the flock acts independently, but needs to know about the current heading and location of the members of its flock. This recipe shows you how to create a scene with two flocks of cubes: one flock of green cubes and, one flock of yellow cubes. To keep things simple, we'll not worry about separation in our recipe.
This recipe builds upon the player-controlled cube Unity project that you created in the first recipe. So, make a copy of this project, open it, and then follow the steps for this recipe.
To make a group of objects flock together, please follow these steps:
m_green
with the Main Color tinted green.m_yellow
with Main Color tinted yellow.Cube-drone
at (0,0,0). Drag the m_yellow
Material into this object.Cube-drone
. Set the Stopping Distance property of the NavMeshAgent component to 2
.Cube-drone
with the following properties:1
0
0.05
Drone
, and add an instance as a component to the Cube-drone
GameObject:using UnityEngine; using System.Collections; public class Drone : MonoBehaviour { private NavMeshAgent navMeshAgent; void Start() { navMeshAgent = GetComponent<NavMeshAgent>(); } public void SetTargetPosition(Vector3 swarmCenterAverage, Vector3 swarmMovementAverage) { Vector3 destination = swarmCenterAverage + swarmMovementAverage; navMeshAgent.SetDestination(destination); } }
dronePrefabYellow
, and from the Hierarchy panel, drag your Cube-boid
GameObject into this Prefab.m_green
Material into the Cube-boid
GameObject.dronePrefabGreen
, and from the Hierarchy panel, drag your Cube-drone
GameObject into this Prefab.Cube-drone
GameObject from the Scene panel.Swarm
class to the Main Camera:using UnityEngine; using System.Collections; using System.Collections.Generic; public class Swarm : MonoBehaviour { public int droneCount = 20; public GameObject dronePrefab; private List<Drone> drones = new List<Drone>(); void Awake() { for (int i = 0; i < droneCount; i++) AddDrone(); } void FixedUpdate() { Vector3 swarmCenter = SwarmCenterAverage(); Vector3 swarmMovement = SwarmMovementAverage(); foreach(Drone drone in drones) drone.SetTargetPosition(swarmCenter, swarmMovement); } private void AddDrone() { GameObject newDroneGO = (GameObject)Instantiate(dronePrefab); Drone newDrone = newDroneGO.GetComponent<Drone>(); drones.Add(newDrone); } private Vector3 SwarmCenterAverage() { // cohesion (swarm center point) Vector3 locationTotal = Vector3.zero; foreach(Drone drone in drones) locationTotal += drone.transform.position; return (locationTotal / drones.Count); } private Vector3 SwarmMovementAverage() { // alignment (swarm direction average) Vector3 velocityTotal = Vector3.zero; foreach(Drone drone in drones) velocityTotal += drone.rigidbody.velocity; return (velocityTotal / drones.Count); } }
prefab_boid_yellow
, from the Project panel, over the public variable of Drone Prefab.Swarm
to this GameObject, and then drag prefab_boid_green
, from the Project panel, over the public variable of Drone Prefab.wall-left
with the following properties:wall-left
object by naming the new object as wall-right
, and change the position of wall-right
to (15, 0.5, 0).wall-top
with the following properties:wall-top
object by naming the new object as wall-bottom
, and change the position of wall-bottom
to (0, 0.5, -10).Sphere-obstacle
with the following properties:Sphere-obstacle
GameObject. Then in the Navigation panel, check the Navigation Static checkbox. Then, click on the Bake button at the bottom of the Navigation panel.The Swarm
class contains three variables:
droneCount
: It is an integer referencing the number of the Swarm
class members createddronePrefab
: It references to the Prefab to be cloned to create swarm membersDrone
: A list of objects that reference drones
, a list of all the scripted Drone
components inside all the Swarm
objects that have been createdUpon creation, as the scene starts, the Swarm
script class Awake()
method loops to create droneCount
swarm members by repeatedly calling the AddDrone()
method. This method instantiates a new GameObject
from the prefab, and then sets the newDrone
variable to be a reference to the Drone-scripted object, inside the new Swarm
class member. In each frame, the FixedUpdate()
method loops through the list of Drone
objects by calling their SetTargetPosition(…)
method, and passing in the Swarm
center location and the average of all the swarm member velocities.
The rest of this Swarm
class is made up of two methods: one (SwarmCenterAverage
) returns a Vector3 object, representing the average position of all the Drone
objects, and the other (SwarmMovementAverage
) returns a Vector3
object, representing the average velocity (movement force) of all the Drone
objects as described in the following list.
SwarmMovementAverage()
:SwarmCenterAverage()
:The core work is undertaken by the Drone
class. Each drone's Start(…)
method finds and caches a reference to its NavMeshAgent component.
Each drone's UpdateVelocity(…)
method takes as input two Vector3 arguments: swarmCenterAverage
and swarmMovementAverage
. This method then calculates the desired new velocity for this Drone (by simply adding the two vectors), and then uses the result (a Vector3 location) to update the NavMeshAgent's target location.
There are some details that you don't want to miss.
Most of the flocking models in modern computing owe much to the work of Craig Reynolds in the 1980s. Learn more about Craig and his boids program at http://en.wikipedia.org/wiki/Craig_Reynolds_(computer_graphics).
3.133.116.137