// Alligning force void Allign(Flocker objToFlock) { Rigidbody2D rbToFlock = objToFlock.GetComponent <Rigidbody2D>(); foreach (Flocker flocker in Flockers) { if (flocker != this) { Vector2 direction = rb.position - rbToFlock.position; // This vector -> scalar can be optimised float distance = magSquare(direction);//.magnitude; if (distance < allignDistance * allignDistance) { localVeloicty = localVeloicty + rbToFlock.velocity; } } } localVeloicty = localVeloicty.normalized; localVeloicty = localVeloicty * maxSpeed; Vector2 localVelocityDifference = localVeloicty - rb.velocity; Vector2 allignForce = localVelocityDifference * allignStrength; // Debug.Log(allignForce); rbToFlock.AddForce(allignForce); }
void MoveTo(BoidNode currentWaypoint) { node = boid.node; // Influence of next checkpoint Vector3 steeringFromTarget = boid.VelocityTowards(currentWaypoint.position, 0, 0.5f); neighbourUnits = Grid.instance.GetUnitNeighbours(boid, false, 3); Vector3 steeringFromUnits = Flocker.ComputeSeparationForce(boid, neighbourUnits, radius, 1); Vector3 steeringFromSurroundings = ComputeSteeringFromObstacles(node, 1, 10); // Compose Vector3 steering = Vector3.ClampMagnitude(steeringFromTarget + steeringFromUnits + steeringFromSurroundings, steeringFromTarget.magnitude); steering = steering / boid.mass; // Floor influence float movementRatio = 1 - node.boidNode.penalty; boid.velocity = Vector3.ClampMagnitude(boid.velocity + steering, boid.maxSpeed * movementRatio); Grid.instance.RemoveUnit(boid); boid.position = boid.predictPosition(Time.deltaTime); Grid.instance.RegisterUnit(boid); transform.position = boid.position; }
public Flock(Flocker initFlocker) //overloaded for deer regrouping { centroid = Vector3.zero; flockDirection = Vector3.zero; flockers = new List <Flocker>(); numFlockers = 1; flockers.Add(initFlocker); flockers [0].flock = this; }
//overloaded for deer regrouping public Flock(Flocker initFlocker) { centroid = Vector3.zero; flockDirection = Vector3.zero; flockers = new List<Flocker>(); numFlockers = 1; flockers.Add (initFlocker); flockers [0].flock = this; }
void ApplyRules() { GameObject[] gos; gos = GlobalFlock.allFlock; Vector3 vCenter = Vector3.zero; Vector3 vAvoid = Vector3.zero; float gSpeed = 0.1f; Vector3 goalPos = GlobalFlock.goalPos; float dist; int groupSize = 0; foreach (GameObject go in gos) { if (go != this.gameObject) { dist = Vector3.Distance(go.transform.position, this.transform.position); if (dist <= neighborDistance) { vCenter += go.transform.position; groupSize++; if (dist < 1.0f) { vAvoid = vAvoid + (this.transform.position - go.transform.position); } Flocker anotherFlock = go.GetComponent <Flocker> (); gSpeed = gSpeed + anotherFlock.speed; } } } if (groupSize > 0) { vCenter = vCenter / groupSize + (goalPos - this.transform.position); speed = gSpeed / groupSize; Vector3 direction = (vCenter + vAvoid) - transform.position; if (direction != Vector3.zero) { transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(direction), rotationSpeed * Time.deltaTime); } } }
// Attracting force void Attract(Flocker objToFlock) { Rigidbody2D rbToFlock = objToFlock.rb; Vector2 direction = rb.position - rbToFlock.position; // float distance = direction.magnitude; // if (distance < repelDistance/3) // return; // Newtonian gravity for POC float forceMagnitude = 1f;//Mathf.Pow(distance, -2); Vector2 force = direction.normalized * forceMagnitude * attractStrength; rbToFlock.AddForce(force); }
// Repelling force void Repel(Flocker objToFlock) { Rigidbody2D rbToFlock = objToFlock.rb; Vector2 direction = rb.position - rbToFlock.position; // This vector -> scalar can be optimised float distance = magSquare(direction);//.magnitude; if (distance < repelDistance * repelDistance) { Vector2 force = -direction.normalized; rbToFlock.AddForce(force * repelStrength); } }
protected int getNearest(List <Flocker> flock) { if (flock == null || flock.Count == 0) { return(-1); } Flocker nearest = flock[0]; int i = 0; for (; i < flock.Count - 1; i++) { if (flock[i] != null && (this.transform.position - flock[i].transform.position).sqrMagnitude < (this.transform.position - nearest.transform.position).sqrMagnitude) { nearest = flock[i]; } } return(i); }
/// <summary> /// After being separated by flee, the deer will try to find each other again and form /// new herds. Will return a force to the nearest deer, and if there is a deer within the regroup /// radius, will form a new flock with that deer and change state. /// </summary> /// <returns>A force that will direct the deer to the nearest detected deer, or 0 if a new flock has been formed.</returns> protected Vector3 regroup() { //find the nearest deer //need masterlist of all deer GameObject[] deer = GameObject.FindGameObjectsWithTag("deer"); List <Flocker> deerFlockers = new List <Flocker>(); foreach (GameObject d in deer) { deerFlockers.Add(d.GetComponent <Flocker>()); } Flocker nearestDeer = deerFlockers[getNearest(deerFlockers)]; if (nearestDeer != null && (nearestDeer.transform.position - this.transform.position).sqrMagnitude < regroupRadius * regroupRadius) { //if that deer has a flock, join it if (nearestDeer.flock != null) { this.flock = nearestDeer.flock; this.flock.addFlocker(this); } //else make a new one with just the two of you else if (this.flock == null) //the extra check is just in case they're trying to make new flocks for each other at the same time, dunno if Unity threads { gm.herds.Add(new Flock(this)); //will assign it to us within the constructor flock.addFlocker(nearestDeer); nearestDeer.flock = flock; flock.seekpoints = gm.getSeekPoints(); flock.seekindex = 0; } return(Vector3.zero); //flag } //else if too far away to join a new flock return(arrive(nearestDeer.transform.position)); }
protected override void Initialize() { boid = new BoidNode(transform.position, radius); transform.localScale = Vector3.one * radius * 2; flock = new Flocker(); }
void Flock(Flocker objToFlock) { Attract(objToFlock); Repel(objToFlock); Allign(objToFlock); }
/// <summary> /// The particular calcSteeringForces used by /// deer. /// </summary> protected override void calcSteeringForces() { Vector3 temp = Vector3.zero; //for prioritizing steeringForce = Vector3.zero; switch (state) { case DeerState.GRAZE: { //if (anim.GetCurrentAnimatorStateInfo(0).nameHash == runHash) //anim.SetTrigger("walkTrigger"); maxSpeed = walkMaxSpeed; if ((this.transform.position - flock.seekpoints[flock.seekindex]).sqrMagnitude < 4) { int currIndex = flock.seekindex; do { flock.seekindex = Random.Range(0, flock.seekpoints.Length); }while (flock.seekindex == currIndex); } steeringForce += wander() * wanderWeight; steeringForce += seek(flock.seekpoints[flock.seekindex]) * seekWeight; steeringForce += this.transform.forward; temp += cohesion(flock.Centroid) * cohesionWeight; //only non-zero conditionally temp += separation(separateDistance) * separationWeight; //also only non-zero conditionally steeringForce += seek(flock.seekpoints[flock.seekindex]) * seekWeight; temp += alignment(flock.FlockDirection) * alignmentWeight; //will always apply a force if called foreach (GameObject obstacle in gm.Obstacles) { temp += avoid(obstacle) * avoidWeight; } steeringForce += temp; steeringForce += flowFollow() * flowWeight; int index = getNearest(gm.Wolves.Flockers); if (index > -1) { //Debug.Log("checking for wolves"); Flocker nearestWolf = gm.Wolves.Flockers[index]; if ((this.transform.position - nearestWolf.transform.position).sqrMagnitude < fleedistance * fleedistance) { Debug.Log("Change State to flee"); foreach (Flocker f in flock.Flockers) { if (f != null) { f.GetComponent <deerScript>().state = DeerState.FLEE; } } if (gm.herds.Contains(flock)) { gm.herds.Remove(flock); //should get garbage collected if we remove our way of getting it } flock = null; } } break; } //fleeing case DeerState.FLEE: { //if (anim.GetCurrentAnimatorStateInfo(0).nameHash == walkHash) //anim.SetTrigger("runTrigger"); maxSpeed = runMaxSpeed; bool safe = true; foreach (Flocker wolf in gm.Wolves.Flockers) { steeringForce += flee(wolf.transform.position); if ((wolf.transform.position - this.transform.position).sqrMagnitude < fleedistance * fleedistance) { safe = false; } } steeringForce += separation(separateDistance); if (safe) { state = DeerState.SEARCH; } break; } //regroup case DeerState.SEARCH: { maxSpeed = walkMaxSpeed; temp += regroup(); if (temp == Vector3.zero) //we found a group! { state = DeerState.GRAZE; } break; } } steeringForce += stayInBounds() * boundsWeight; base.calcSteeringForces(); }
public void addFlocker(Flocker f) { flockers.Add(f); numFlockers++; }
private void Start() { kinematic = GetComponent <Kinematic>(); switch (moveType) { case SteeringType.Pursue: pursueAI = new Pursue(); pursueAI.character = kinematic; pursueAI.target = target; break; case SteeringType.Evade: evadeAI = new Evade(); evadeAI.character = kinematic; evadeAI.target = target; break; case SteeringType.FollowPath: followAI = new PathFollow(); followAI.character = kinematic; followAI.path = pathOfObjects; break; case SteeringType.Seek: seekAI = new Seek(); seekAI.character = kinematic; seekAI.target = target; break; case SteeringType.Flee: fleeAI = new Flee(); fleeAI.character = kinematic; fleeAI.target = target; break; case SteeringType.Seperation: seperationAI = new Seperation(); seperationAI.character = kinematic; seperationAI.targets = seperateObstacles; break; case SteeringType.Arrive: arriveAI = new Arrive(); arriveAI.character = kinematic; arriveAI.target = target; break; case SteeringType.CollisionAvoidance: avoidAI = new CollisionAvoidance(); avoidAI.character = kinematic; avoidAI.targets = collisionTargets; break; case SteeringType.ObstacleAvoidance: obstacleAI = new ObstacleAvoidance(); obstacleAI.character = kinematic; break; case SteeringType.Flocking: flockAI = new Flocker(); break; case SteeringType.None: break; } switch (lookType) { case LookType.Align: alignAI = new Align(); alignAI.character = kinematic; alignAI.target = target; break; case LookType.Face: faceAI = new Face(); faceAI.character = kinematic; faceAI.target = target; break; case LookType.LookWhereGoing: lookAI = new LookWhereGoing(); lookAI.character = kinematic; break; } }