// SEPARATION: Steering to avoid colliding or crowing with other flockmates private Vector3 CalculateSeparation(int boidIndex) { ComputeBoid boid = m_boids[boidIndex]; if (boid.GetNeighbourCount() == 0) { return(Vector3.zero); } Vector3 separationForce = Vector3.zero; Vector3 boidPosition = boid.transform.position; float separationDistSqr = m_separationValue * m_separationValue; foreach (ComputeBoid neighbour in boid.IterateNeighbours()) { Vector3 difference = boidPosition - neighbour.transform.position; float distanceSqr = difference.sqrMagnitude; if (distanceSqr < separationDistSqr) { // Needs separating Vector3 separate = difference; separate.Normalize(); separate = separate / distanceSqr; separationForce += separate; } } return(separationForce); }
// ALIGNMENT: Steering to move with the average heading of flockmates private Vector3 CalculateAlignment(int boidIndex) { ComputeBoid boid = m_boids[boidIndex]; if (boid.GetNeighbourCount() == 0) { return(Vector3.zero); } Vector3 alignmentForce = Vector3.zero; Vector3 sumHeading = Vector3.zero; foreach (ComputeBoid neighbour in boid.IterateNeighbours()) { sumHeading = neighbour.GetBoidVelocity().normalized; } alignmentForce = sumHeading / boid.GetNeighbourCount(); return(alignmentForce); }
private void CalculateRules(int boidIndex, ref Vector3 sepForce, ref Vector3 alignForce, ref Vector3 cohForce) { ComputeBoid boid = m_boids[boidIndex]; if (boid.GetNeighbourCount() == 0) { return; } Vector3 boidPosition = boid.transform.position; sepForce = Vector3.zero; alignForce = Vector3.zero; cohForce = Vector3.zero; float separationDistSqr = m_separationValue * m_separationValue; Vector3 sumHeading = Vector3.zero; Vector3 averagePosition = Vector3.zero; foreach (ComputeBoid neighbour in boid.IterateNeighbours()) { sumHeading = neighbour.GetBoidVelocity().normalized; averagePosition += neighbour.transform.position; Vector3 difference = boidPosition - neighbour.transform.position; float distanceSqr = difference.sqrMagnitude; if (distanceSqr < separationDistSqr) { // Needs separating Vector3 separate = difference; separate.Normalize(); separate = separate / distanceSqr; sepForce += separate; } } alignForce = sumHeading / boid.GetNeighbourCount(); averagePosition /= boid.GetNeighbourCount(); cohForce = averagePosition - m_boids[boidIndex].transform.position; }
// COHESION: Steering to move towards the average position of flockmates private Vector3 CalculateCohesion(int boidIndex) { ComputeBoid boid = m_boids[boidIndex]; if (boid.GetNeighbourCount() == 0) { return(Vector3.zero); } Vector3 cohesionForce = Vector3.zero; Vector3 averagePosition = Vector3.zero; foreach (ComputeBoid neighbour in boid.IterateNeighbours()) { averagePosition += neighbour.transform.position; } averagePosition /= boid.GetNeighbourCount(); cohesionForce = averagePosition - m_boids[boidIndex].transform.position; return(cohesionForce); }
public void AddNeighbour(ComputeBoid neighbour) { m_neighbours.Add(neighbour); }
void FixedUpdate() { // Find boids neighbours PerformNeighbourSearch(); if (!m_updatePosition) { return; } for (int i = 0; i < m_boids.Length; ++i) { ComputeBoid boid = m_boids[i]; Vector3 newVelocity = Vector3.zero; Vector3 separation = Vector3.zero; Vector3 alignment = Vector3.zero; Vector3 cohesion = Vector3.zero; CalculateRules(i, ref separation, ref alignment, ref cohesion); // 1) SEPARATION if (m_enableSeparation) { //separation = CalculateSeparation( i ); if (m_drawSeparationDebugRays && separation.sqrMagnitude > 0.0f) { DrawRedRay(boid, separation); } newVelocity += separation * m_separationFactor; } // 2) ALIGNMENT if (m_enableAlignment) { //alignment = CalculateAlignment( i ); if (m_drawAlignmentDebugRays && alignment.sqrMagnitude > 0.0f) { DrawRay(boid, alignment, Color.blue); } newVelocity += alignment * m_alignmentFactor; } // 3) COHESION if (m_enableCohesion) { //cohesion = CalculateCohesion( i ); if (m_drawCohesionDebugRays && cohesion.sqrMagnitude > 0.0f) { DrawRay(boid, cohesion, Color.green); } newVelocity += cohesion * m_cohesionFactor; } if (m_drawBoidAxis) { boid.DrawDebugAxis(); } boid.SetBoidVelocity(newVelocity); boid.UpdatePosition(); boid.ClearNeighbours(); } }
private void DrawRay(ComputeBoid boid, Vector3 direction, Color colour) { Debug.DrawRay(boid.transform.position, direction, colour); }
private void DrawRedRay(ComputeBoid boid, Vector3 direction) { DrawRay(boid, direction, Color.red); }