Flocking

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
m (Text replace - "</javascript>" to "</syntaxhighlight>")
(indent fix and bug fix)
Line 13: Line 13:
 
[[Media:FlockingCS.zip|C# version]] by [[User:Benblo|Benoit FOULETIER]] (basically just converted the original, cleaned up and optimized a bit... the logic is identical.)
 
[[Media:FlockingCS.zip|C# version]] by [[User:Benblo|Benoit FOULETIER]] (basically just converted the original, cleaned up and optimized a bit... the logic is identical.)
  
==JavaScript - Boid Controller.js==
+
==JavaScript - BoidController.js==
 
This script creates and collects information on the boids.  
 
This script creates and collects information on the boids.  
 
It Uses the surface of the controller's collider as spawn points.
 
It Uses the surface of the controller's collider as spawn points.
  
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
var minVelocity : float = 5;
+
#pragma strict
var maxVelocity : float = 20;
+
 
var randomness : float = 1;  
+
var minVelocity : float = 5;
var flockSize : int = 20;
+
var maxVelocity : float = 20;
 +
var randomness : float = 1;  
 +
var flockSize : int = 20;
 
var prefab : GameObject;  
 
var prefab : GameObject;  
 
var chasee : GameObject;
 
var chasee : GameObject;
Line 28: Line 30:
 
var flockVelocity : Vector3;
 
var flockVelocity : Vector3;
  
private var boids;
+
private var boids : Array;
  
 
function Start() {
 
function Start() {
boids = new Array(flockSize);
+
    boids = new Array(flockSize);
for (var i=0; i<flockSize; i++) {
+
    for (var i=0; i<flockSize; i++) {
var position = Vector3(
+
        var position = Vector3(
Random.value*collider.bounds.size.x,
+
            Random.value * collider.bounds.size.x,
Random.value*collider.bounds.size.y,
+
            Random.value * collider.bounds.size.y,
Random.value*collider.bounds.size.z
+
            Random.value * collider.bounds.size.z
      ) - collider.bounds.extents;
+
        ) - collider.bounds.extents;
  
var boid = Instantiate(prefab, transform.position, transform.rotation);
+
        var boid = Instantiate(prefab, transform.position, transform.rotation);
boid.transform.parent = transform;
+
        boid.transform.parent = transform;
boid.transform.localPosition = position;
+
        boid.transform.localPosition = position;
boid.GetComponent("Boid Flocking").setController(gameObject);
+
        boid.GetComponent.<BoidFlocking>().setController(gameObject);
boids[i] = boid;
+
        boids[i] = boid;
}
+
    }
 
}
 
}
  
function Update () {  
+
function Update () {
  var theCenter = Vector3.zero;
+
    var theCenter = Vector3.zero;
  var theVelocity = Vector3.zero;
+
    var theVelocity = Vector3.zero;
  
  for (var boid : GameObject in boids) {
+
    for (var boid : GameObject in boids) {
theCenter       = theCenter + boid.transform.localPosition;
+
        theCenter = theCenter + boid.transform.localPosition;
theVelocity     = theVelocity + boid.rigidbody.velocity;
+
        theVelocity = theVelocity + boid.rigidbody.velocity;
  }
+
    }
  
flockCenter = theCenter/(flockSize);
+
    flockCenter = theCenter/(flockSize);
flockVelocity = theVelocity/(flockSize);
+
    flockVelocity = theVelocity/(flockSize);
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
==JavaScript - Boid Flocking.js==
+
==JavaScript - BoidFlocking.js==
  
 
Each boid runs this script. It handles randomness, clumping behavior, velocity matching behavior and target following behavior.  
 
Each boid runs this script. It handles randomness, clumping behavior, velocity matching behavior and target following behavior.  
Line 68: Line 70:
  
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
var Controller : GameObject;
+
#pragma strict
 +
 
 +
private var Controller : GameObject;
  
 
private var inited = false;
 
private var inited = false;
Line 77: Line 81:
  
 
function Start () {
 
function Start () {
StartCoroutine("boidSteering");
+
    StartCoroutine("boidSteering");
 
}
 
}
  
 
function boidSteering () {
 
function boidSteering () {
while(true) {
+
    while(true) {
if (inited) {
+
        if (inited) {
rigidbody.velocity = rigidbody.velocity + calc() * Time.deltaTime;
+
            rigidbody.velocity = rigidbody.velocity + calc() * Time.deltaTime;
+
// enforce minimum and maximum speeds for the boids
+
var speed = rigidbody.velocity.magnitude;
+
if (speed > maxVelocity) {
+
rigidbody.velocity = rigidbody.velocity.normalized * maxVelocity;
+
} else if (speed < minVelocity) {
+
rigidbody.velocity = rigidbody.velocity.normalized * minVelocity;
+
}
+
}
+
waitTime = Random.Range(0.3, 0.5);
+
yield WaitForSeconds(waitTime);
+
}
+
}
+
  
 +
            // enforce minimum and maximum speeds for the boids
 +
            var speed = rigidbody.velocity.magnitude;
 +
            if (speed > maxVelocity) {
 +
                rigidbody.velocity = rigidbody.velocity.normalized * maxVelocity;
 +
            } else if (speed < minVelocity) {
 +
                rigidbody.velocity = rigidbody.velocity.normalized * minVelocity;
 +
            }
 +
        }
 +
    var waitTime = Random.Range(0.3, 0.5);
 +
    yield WaitForSeconds(waitTime);
 +
    }
 +
}
  
 
function calc () {
 
function calc () {
var randomize = Vector3((Random.value *2) -1, (Random.value * 2) -1, (Random.value * 2) -1);
+
    var randomize = Vector3((Random.value *2) -1, (Random.value * 2) -1, (Random.value * 2) -1);
+
randomize.Normalize();
+
  
flockCenter = Controller.GetComponent("Boid Controller").flockCenter;  
+
    randomize.Normalize();
flockVelocity = Controller.GetComponent("Boid Controller").flockVelocity;
+
 
follow = chasee.transform.localPosition;
+
    var flockCenter : Vector3 = Controller.GetComponent.<BoidController>().flockCenter;
+
    var flockVelocity : Vector3 = Controller.GetComponent.<BoidController>().flockVelocity;
flockCenter = flockCenter - transform.localPosition;
+
    var follow : Vector3 = chasee.transform.localPosition;
flockVelocity = flockVelocity - rigidbody.velocity;
+
 
follow = follow - transform.localPosition;
+
    flockCenter = flockCenter - transform.localPosition;
+
    flockVelocity = flockVelocity - rigidbody.velocity;
return (flockCenter + flockVelocity + follow*2 + randomize*randomness);
+
    follow = follow - transform.localPosition;
 +
 
 +
    return (flockCenter + flockVelocity + follow*2 + randomize*randomness);
 
}
 
}
  
 
function setController (theController : GameObject) {
 
function setController (theController : GameObject) {
Controller = theController;
+
    Controller = theController;
minVelocity = Controller.GetComponent("Boid Controller").minVelocity;
+
    minVelocity = Controller.GetComponent.<BoidController>().minVelocity;
maxVelocity = Controller.GetComponent("Boid Controller").maxVelocity;
+
    maxVelocity = Controller.GetComponent.<BoidController>().maxVelocity;
randomness = Controller.GetComponent("Boid Controller").randomness;
+
    randomness = Controller.GetComponent.<BoidController>().randomness;
chasee = Controller.GetComponent("Boid Controller").chasee;
+
    chasee = Controller.GetComponent.<BoidController>().chasee;
inited = true;
+
    inited = true;
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
  
==JavaScript - Boid Watcher.js==
+
==JavaScript - BoidWatcher.js==
  
 
A camera script, watches the center of the flock.
 
A camera script, watches the center of the flock.
  
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
 +
#pragma strict
 +
 
var boidController : Transform;
 
var boidController : Transform;
  
 
function LateUpdate () {
 
function LateUpdate () {
if (boidController) {
+
    if (boidController) {
var watchPoint : Vector3 = boidController.GetComponent("Boid Controller").flockCenter;
+
        var watchPoint : Vector3 = boidController.GetComponent.<BoidController>().flockCenter;
transform.LookAt(watchPoint+boidController.transform.position);
+
        transform.LookAt(watchPoint+boidController.transform.position);  
}
+
    }
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>

Revision as of 07:53, 21 October 2013

Contents

Information

Here's a set of flocking scripts, They will follow a target, have controls for min speed, max speed, randomness.

Uses the physics engine and oversized sphere colliders to keep the boids apart.

Use the example scene in the unityPackage to figure out how to hook it all together.

Download Package

Download Flocking.unityPackage.zip

C# version by Benoit FOULETIER (basically just converted the original, cleaned up and optimized a bit... the logic is identical.)

JavaScript - BoidController.js

This script creates and collects information on the boids. It Uses the surface of the controller's collider as spawn points.

#pragma strict
 
var minVelocity : float = 5;
var maxVelocity : float = 20;
var randomness : float = 1; 
var flockSize : int = 20;
var prefab : GameObject; 
var chasee : GameObject;
 
var flockCenter : Vector3;
var flockVelocity : Vector3;
 
private var boids : Array;
 
function Start() {
    boids = new Array(flockSize);
    for (var i=0; i<flockSize; i++) {
        var position = Vector3(
            Random.value * collider.bounds.size.x,
            Random.value * collider.bounds.size.y,
            Random.value * collider.bounds.size.z
        ) - collider.bounds.extents;
 
        var boid = Instantiate(prefab, transform.position, transform.rotation);
        boid.transform.parent = transform;
        boid.transform.localPosition = position;
        boid.GetComponent.<BoidFlocking>().setController(gameObject);
        boids[i] = boid;
    }
}
 
function Update () {
    var theCenter = Vector3.zero;
    var theVelocity = Vector3.zero;
 
    for (var boid : GameObject in boids) {
        theCenter = theCenter + boid.transform.localPosition;
        theVelocity = theVelocity + boid.rigidbody.velocity;
    }
 
    flockCenter = theCenter/(flockSize);
    flockVelocity = theVelocity/(flockSize);
}

JavaScript - BoidFlocking.js

Each boid runs this script. It handles randomness, clumping behavior, velocity matching behavior and target following behavior.

This could be updated to include weighting factors for velocity matching, target following and clumping, as has been done for randomness.

#pragma strict
 
private var Controller : GameObject;
 
private var inited = false;
private var minVelocity : float;
private var maxVelocity : float;
private var randomness : float;
private var chasee : GameObject;
 
function Start () {
    StartCoroutine("boidSteering");
}
 
function boidSteering () {
    while(true) {
        if (inited) {
            rigidbody.velocity = rigidbody.velocity + calc() * Time.deltaTime;
 
            // enforce minimum and maximum speeds for the boids
            var speed = rigidbody.velocity.magnitude;
            if (speed > maxVelocity) {
                rigidbody.velocity = rigidbody.velocity.normalized * maxVelocity;
            } else if (speed < minVelocity) {
                rigidbody.velocity = rigidbody.velocity.normalized * minVelocity;
            }
        }
    var waitTime = Random.Range(0.3, 0.5);
    yield WaitForSeconds(waitTime);
    }
}
 
function calc () {
    var randomize = Vector3((Random.value *2) -1, (Random.value * 2) -1, (Random.value * 2) -1);
 
    randomize.Normalize();
 
    var flockCenter : Vector3 = Controller.GetComponent.<BoidController>().flockCenter;
    var flockVelocity : Vector3 = Controller.GetComponent.<BoidController>().flockVelocity;
    var follow : Vector3 = chasee.transform.localPosition;
 
    flockCenter = flockCenter - transform.localPosition;
    flockVelocity = flockVelocity - rigidbody.velocity;
    follow = follow - transform.localPosition;
 
    return (flockCenter + flockVelocity + follow*2 + randomize*randomness);
}
 
function setController (theController : GameObject) {
    Controller = theController;
    minVelocity = Controller.GetComponent.<BoidController>().minVelocity;
    maxVelocity = Controller.GetComponent.<BoidController>().maxVelocity;
    randomness = Controller.GetComponent.<BoidController>().randomness;
    chasee = Controller.GetComponent.<BoidController>().chasee;
    inited = true;
}

JavaScript - BoidWatcher.js

A camera script, watches the center of the flock.

#pragma strict
 
var boidController : Transform;
 
function LateUpdate () {
    if (boidController) {
        var watchPoint : Vector3 = boidController.GetComponent.<BoidController>().flockCenter;
        transform.LookAt(watchPoint+boidController.transform.position);    
    }
}
Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox