/// <summary> /// This behaviour returns a force that will steer the agent towards to agent thats trying to evade the pursuing agent. /// </summary> /// <returns>Steering Force</returns> public Vector2D Pursuit(FlyingEntity evader) { /* If the evader is ahead and facing the agent then we can just seek * for the evader's current position. */ Vector2D ToEvader = evader.Pos - _flyingEntity.Pos; double RelativeHeading = _flyingEntity.Heading.Dot(evader.Heading); if ((ToEvader.Dot(_flyingEntity.Heading) > 0) && (RelativeHeading < -0.95)) // Acos(0.95)= 18 degrees { return(Seek(evader.Pos)); } // If this agent isn't ahead the position of the evader will be predicted. /* The lookahead time is propotional to the distance between the evader * and the pursuer; and is inversely proportional to the sum of the * agent's velocities */ double LookAheadTime = ToEvader.Length() / (_flyingEntity.MaxSpeed + evader.Speed()); // Now seek to the predicted future position of the evader. return(Seek(evader.Pos + evader.Velocity * LookAheadTime)); }
public SteeringBehavior(FlyingEntity agent) { _flyingEntity = agent; TargetAgent1 = null; TargetAgent2 = null; decelerationRate = DecelerationRate.NORMAL; SummingMethod = SumMethod.WEIGHTED_AVG; _path = new Path { Looped = true }; }
private float FitnessFunction(int index) { float score = 0; FlyingEntity flyingEntity = flyingEntities[index]; float fitnessTime = 1 - Mathf.Clamp(Mathf.InverseLerp(0f, 30f, flyingEntities[index].timer), 0f, 1f); float fitnessDistance = 1 - Mathf.Clamp(Mathf.InverseLerp(0f, 100f, Vector3.Distance(flyingEntities[index].gameObject.transform.position, FlyingEntity.target.transform.position)), 0f, 1f); float crashed = flyingEntities[index].crashed ? 0.0f : 1.0f; score += fitnessTime + fitnessDistance + crashed; return(score / 3); }
// Use this for initialization void Start() { random = new System.Random(); ga = new MyGeneticAlgorithm <float>(population, 3, random, GetRandomEntityValues, FitnessFunction, 5, 0.01f); flyingEntities = new FlyingEntity[population]; for (int i = 0; i < population; i++) { FlyingEntity flyingEntity = Instantiate(FlyingEntityPrefab, spawnPosition.position, Quaternion.identity).GetComponent <FlyingEntity>(); flyingEntities[i] = flyingEntity; flyingEntities[i].entityValues = new FlyingEntityValues(); flyingEntity.entityValues.DistanceForCollisionCheck = ga.Population[i].Genes[0]; flyingEntity.entityValues.DistanceForCollisionLeftAndRight = ga.Population[i].Genes[1]; flyingEntity.entityValues.Speed = ga.Population[i].Genes[2]; } }
/// <summary> /// Returns a steering force which directs the agent away from the pursuer. /// </summary> /// <param name="pursuer"></param> /// <returns>Steering Force</returns> public Vector2D Evade(FlyingEntity pursuer) { Vector2D ToPursuer = pursuer.Pos - _flyingEntity.Pos; if (_evadeThreatRangeOn) { if (ToPursuer.LengthSq() > _evadeThreatRange * _evadeThreatRange) { return(Vector2D.Zero); } } /* The lookahead time is propotional to the distance between the pursuer * and the pursuer; and is inversely proportional to the sum of the * agents' velocities. */ double LookAheadTime = ToPursuer.Length() / (_flyingEntity.MaxSpeed + pursuer.Speed()); // Now flee away from predicted future position of the pursuer. return(Flee(pursuer.Pos + pursuer.Velocity * LookAheadTime)); }
/// <summary> /// Tags any entities contained in a std container that are within the /// radius of the vehicle specified. /// </summary> /// <param name="entity"></param> /// <param name="radius"></param> public void TagVehiclesWithinViewRange(FlyingEntity FlyingEntity, double radius) { foreach (FlyingEntity flyingEntity in flyingEntities) { // First clear any current tag. FlyingEntity.Tag = false; Vector2D to = flyingEntity.Pos - FlyingEntity.Pos; /* The bounding radius of the other is taken into account by adding it * to the range. */ double range = radius + flyingEntity.BoundingRadius; /* If entity within range, tag for further consideration. (working in * distance-squared space to avoid sqrts) */ if ((flyingEntity != FlyingEntity) && (to.LengthSq() < range * range)) { flyingEntity.Tag = true; } }// Next entity. }
/// <summary> /// Makes position of Vehicle and targetPosition equal if the difference between them is very small. /// </summary> /// <param name="flyingEntity"></param> /// <param name="targetPos"></param> public bool ClampPositions(ref FlyingEntity flyingEntity, Vector2D targetPos) { float deltaX = flyingEntity.Pos.x - targetPos.x; float deltaY = flyingEntity.Pos.y - targetPos.y; if (-10 < deltaX && deltaX < 10) { flyingEntity.Pos.x = targetPos.x; } if (-10 < deltaY && deltaY < 10) { flyingEntity.Pos.y = targetPos.y; } ; if ((-10 < deltaX && deltaX < 10) && (-10 < deltaY && deltaY < 10)) { flyingEntity.Pos = targetPos; return(true); } ; return(false); }
// Update is called once per frame void Update() { if (Input.GetKeyDown(KeyCode.Space)) { ga.NewGeneration(); for (int i = 0; i < flyingEntities.Length; i++) { Destroy(flyingEntities[i].gameObject); flyingEntities[i] = null; } for (int i = 0; i < population; i++) { FlyingEntity flyingEntity = Instantiate(FlyingEntityPrefab, spawnPosition.position, Quaternion.identity).GetComponent <FlyingEntity>(); flyingEntities[i] = flyingEntity; flyingEntity.entityValues.DistanceForCollisionCheck = ga.Population[i].Genes[0]; flyingEntity.entityValues.DistanceForCollisionLeftAndRight = ga.Population[i].Genes[1]; flyingEntity.entityValues.Speed = ga.Population[i].Genes[2]; } } }
/// <summary> /// Produces a steering force that keeps a FlyingEntity at a specified offset /// from a leader FlyingEntity. /// </summary> /// <param name="leader"></param> /// <param name="offset"></param> /// <returns></returns> public Vector2D OffsetPursuit(FlyingEntity leader, int offset) { return(Arrive(leader.Pos - leader.Heading * offset, DecelerationRate.FAST)); }