public void TagAIAgentWithinViewRange(AIAgent entity, float radius) { foreach (KeyValuePair <int, AIGroup> ai in m_aiGroup) { List <AIAgent> entities = ai.Value.Agents(); for (int i = 0; i < entities.Count; ++i) { AIAgent curEntity = entities[i]; //first clear any current tag curEntity.UnTagging(); Vector3 to = curEntity.VPos() - entity.VPos(); //the bounding radius of the other is taken into account by adding it //to the range float range = radius + curEntity.BRadius(); //if entity within range, tag for further consideration. (working in //distance-squared space to avoid sqrts) if ((curEntity.GetHashCode() != entity.GetHashCode()) && (to.sqrMagnitude < range * range)) { curEntity.Tagging(); } } } }
public void AIUpdate() { //update the time elapsed //keep a record of its old position so we can update its cell later //in this method Vector3 OldVelocity = aiAgent.Velocity(); Vector3 SteeringForce = Vector3.zero; //calculate the combined force from each steering behavior in the //vehicle's list SteeringForce = steeringBehaviour.Calculate(); //Acceleration = Force/Mass Vector3 acceleration = SteeringForce / aiAgent.Mass(); Vector3 gravityaccel = steeringBehaviour.GravityAccel(); grounded = (gravityaccel.magnitude > 0) ? true : false; aiAgent.Update(acceleration, gravityaccel, useWrapAround, Time.deltaTime); Vector3 vPos = aiAgent.VPos(); vPos.y = steeringBehaviour.GravityTruncate(vPos.y); aiAgent.SetVPos(vPos); //EnforceNonPenetrationConstraint(this, World()->Agents()); //update the vehicle's current cell if space partitioning is turned on if (isSmoothingOn()) { m_vSmoothedHeading = m_pHeadingSmoother.Update(aiAgent.Heading()); } //moveState if (steeringBehaviour.IsSteering()) { float epsillon = 0.01f; if (MathUtil.Equal(aiAgent.Velocity(), Vector3.zero, epsillon) && OldVelocity.magnitude >= epsillon) { if (onMoveComplete != null) { onMoveComplete(aiAgent, steeringBehaviour, MoveCompleteState.Reached); } } else if (gravityaccel.magnitude <= 0 && gravityaccel_old.magnitude > 0) { if (onMoveComplete != null) { onMoveComplete(aiAgent, steeringBehaviour, MoveCompleteState.Landed); } } } gameObject.transform.position = aiAgent.VPos(); if (useRotation) { Vector3 vDir = aiAgent.Heading(); if (vDir.magnitude > 0) { gameObject.transform.rotation = Quaternion.LookRotation(vDir); } } Vector3 target = gameObject.transform.position + gameObject.transform.rotation * Vector3.forward * aiAgent.BRadius(); gravityaccel_old = gravityaccel; DebugExtension.DebugCircle(target, 0.5f); }
/** * Given a vector of obstacles, this method returns a steering force * that will prevent the agent colliding with the closest obstacle */ private Vector3 ObstacleAvoidance(List <AIObject> obstacles) { //* //the detection box length is proportional to the agent's velocity m_fDBoxLength = minDetectionBoxLength + (m_entity.Speed() / m_entity.MaxSpeed()) * minDetectionBoxLength; //tag all obstacles within range of the box for processing m_entity.World().TagObstaclesWithinViewRange(m_entity, m_fDBoxLength); //this will keep track of the closest intersecting obstacle (CIB) AIObject ClosestIntersectingObstacle = null; //this will be used to track the distance to the CIB float DistToClosestIP = float.MaxValue; //this will record the transformed local coordinates of the CIB Vector3 LocalPosOfClosestObstacle = Vector3.zero; IEnumerator <AIObject> it = obstacles.GetEnumerator(); for (int i = 0; i < obstacles.Count; ++i) { //if the obstacle has been tagged within range proceed AIObject curOb = obstacles[i]; if (curOb.Tag) { //calculate this obstacle's position in local space Vector3 LocalPos = MathUtil.PointToLocalSpace(curOb.VPos(), m_entity.Heading(), m_entity.Side(), m_entity.VPos()); // entity Heading and LocalPos is if (Vector3.Dot(LocalPos, Vector3.forward) > 0) { //than its radius + half the width of the detection box then there //is a potential intersection. float ExpandedRadius = curOb.BRadius() + m_entity.BRadius(); if (Mathf.Abs(LocalPos.x) < ExpandedRadius) { //test to see if this is the closest so far. If it is keep a //record of the obstacle and its local coordinates if (LocalPos.magnitude < DistToClosestIP) { DistToClosestIP = LocalPos.magnitude; ClosestIntersectingObstacle = curOb; LocalPosOfClosestObstacle = LocalPos; } } } } } //if we have found an intersecting obstacle, calculate a steering //force away from it Vector3 steeringForce = Vector3.zero; if (ClosestIntersectingObstacle != null) { //should be //the closer the agent is to an object, the stronger the //steering force should be float multiplier = 1.0f + (m_fDBoxLength - LocalPosOfClosestObstacle.z) / m_fDBoxLength; //calculate the lateral force steeringForce.x = (ClosestIntersectingObstacle.BRadius() - LocalPosOfClosestObstacle.x) * multiplier; //apply a braking force proportional to the obstacles distance from //the vehicle. float BrakingWeight = 0.2f; steeringForce.z = (ClosestIntersectingObstacle.BRadius() - LocalPosOfClosestObstacle.z) * BrakingWeight; } //finally, convert the steering vector from local to world space return(MathUtil.VectorToWorldSpace(steeringForce, m_entity.Heading(), m_entity.Side())); }