/// <summary> /// The WallAvoidance behavior. Will return a steering based on finding collisions and avoid them /// </summary> /// <param name="facingDir">The direction we are facing</param> /// <returns></returns> public Vector3 GetSteering(Vector3 facingDir) { var acceleration = Vector3.zero; /* Creates the ray direction vector */ var rayDirs = new Vector3[3]; rayDirs[0] = facingDir.normalized; var orientation = Mathf.Atan2(_rb.velocity.x, _rb.velocity.z); rayDirs[1] = OrientationToVector(orientation + LookToSideAngle * Mathf.Deg2Rad); rayDirs[2] = OrientationToVector(orientation - LookToSideAngle * Mathf.Deg2Rad); /* If no collision do nothing */ if (FindObstacle(rayDirs, out var hit) == false) { return(acceleration); } /* Create a target away from the wall to seek */ var targetPosition = hit.point + hit.normal * WallAvoidDistance; /* If velocity and the collision normal are parallel then move the target a bit to the left or right of the normal */ var cross = Vector3.Cross(_rb.velocity, hit.normal); if (cross.magnitude < 0.005f) { targetPosition += new Vector3(-hit.normal.z, hit.normal.y, hit.normal.x); } return(_seek.GetSteering(targetPosition, MaxAcceleration)); }
public Steering GetSteering() { if (path == null || currentPoint >= path.Length) { if (path == null) { Debug.LogError("Path is invalid: Null"); } if (currentPoint >= path.Length) { Debug.LogError("Path is invalid: Out of bounds"); } return(new Steering()); } UpdateExtraRadius(); float arrivalRadius2 = arrivalRadius + extraRadius; float distance = Util.HorizontalDist(path[currentPoint], npc.position); if (distance < arrivalRadius2) { if (currentPoint != Mathf.Min(currentPoint + 1, path.Length - 1)) { extraRadius = 0; near = false; } currentPoint = Mathf.Min(currentPoint + 1, path.Length - 1); //When it reaches the last stays on it //if (currentPoint == path.Length - 2) // return Arrive.GetSteering(path[currentPoint], npc, 1f, maxAccel /*50*/); } return(Seek.GetSteering(path[currentPoint], npc, maxAccel /*50*/, false)); }
/// <summary> /// The Pursue behavior. Will return a steering based on prediction of the movement of the target /// </summary> /// <param name="target"></param> /// <returns></returns> public Vector3 GetSteering(Rigidbody target) { /* Calculate the distance to the target */ var direction = target.position - transform.position; var distance = direction.magnitude; /* Get the character's speed */ var speed = _rb.velocity.magnitude; /* Calculate the prediction time */ float prediction; if (speed <= distance / MaxPrediction) { prediction = MaxPrediction; } else { prediction = distance / speed; } /* Put the target together based on where we think the target will be */ var predictedTarget = target.position + target.velocity * prediction; return(_seek.GetSteering(predictedTarget)); }
public static Steering GetSteering(Agent npc, float threshold, float decayCoefficient, float maxAccel, bool visibleRays) { Steering steering = new Steering(); int neighbours = 0; Vector3 centerOfMass = Vector3.zero; int layerMask = 1 << 9; Collider[] hits = Physics.OverlapSphere(npc.position, threshold, layerMask); foreach (Collider coll in hits) { //Comprobar con un SphereCast, en vez de Tag quiza usar Layers Agent agent = coll.GetComponent <Agent>(); float distance = Util.HorizontalDist(agent.position, npc.position); if (agent != npc && distance < threshold) { centerOfMass += agent.position; neighbours++; } } if (neighbours > 0) { centerOfMass /= neighbours; return(Seek.GetSteering(centerOfMass, npc, maxAccel, visibleRays)); } return(steering); }
public Steering Apply() { Steering st = new Steering(); if (finished) { callback(true); return(st); } if (followPath.HasPath()) { if (Time.fixedTime - timeStamp > reconsiderSeconds) { timeStamp = Time.fixedTime; SetNewTarget(target, false); } } else { st += Seek.GetSteering(target, agent, 500f); //If path has not been solved yet just do Seek. } st += followPath.Apply(); //If there is no path just avoid collisions return(st); }
void Update() { SteeringOutput steering; //Update position and rotation transform.position += linearVelocity * Time.deltaTime; Vector3 angularIncrement = new Vector3(0, angularVelocity * Time.deltaTime, 0); transform.eulerAngles += angularIncrement; switch (type) { case SteeringType.Pursue: steering = pursueAI.GetSteering(); break; case SteeringType.Evade: steering = evadeAI.GetSteering(); break; case SteeringType.FollowPath: steering = followAI.GetSteering(); break; case SteeringType.Seek: steering = seekAI.GetSteering(); break; case SteeringType.Flee: steering = fleeAI.GetSteering(); break; case SteeringType.Seperation: steering = seperationAI.GetSteering(); break; default: steering = seekAI.GetSteering(); break; } linearVelocity += steering.linear * Time.deltaTime; angularVelocity += steering.angular * Time.deltaTime; //Update kinematic reference with complex data it can't get by itself kinematic.GetData(steering); }
public override void GetAction(AIInputController script) { script.steering += Seek.GetSteering(script.target._static.position, script.self._static.position, script.tank.maxSpeed).Weight(1.0f); if (script.CheckShieldDanger()) { transitions[0].bTriggered = true; } }
public static Steering GetSteering(Vector3 target, Agent npc, float maxAccel, bool visibleRays = false) { Steering steering = -Seek.GetSteering(target, npc, maxAccel, false); if (visibleRays) { drawRays(npc.position, steering.linear, Color.magenta); } return(steering); }
public Steering GetSteering() { if (path == null || currentPoint >= path.Length) { if (path == null) { Debug.LogError("Path is invalid: Null"); } if (currentPoint >= path.Length) { Debug.LogError("Path is invalid: Out of bounds"); } return(new Steering()); } float distance = Util.HorizontalDist(path[currentPoint], npc.position); if (distance < arrivalRadius) { if (type == FollowT.STAY) { currentPoint = Mathf.Min(currentPoint + 1, path.Length - 1); //When it reaches the last stays on it //if (currentPoint == path.Length - 1) // return Arrive.GetSteering(path[currentPoint], npc, 1f,maxAccel /*50*/); } else if (type == FollowT.BACK) { currentPoint += direction; //Needs to be run twice, since the currentPoint will remain the same the first time if (currentPoint >= path.Length || currentPoint < 0) { direction = 1 - direction; currentPoint += direction; } } else if (type == FollowT.LOOP) { //When it reaches the last it starts from the begging currentPoint++; if (currentPoint >= path.Length) { currentPoint = 0; } } } return(Seek.GetSteering(path[currentPoint], npc, maxAccel /*50*/, visibleRays)); }
/// <summary> /// The Wander behavior. Will return a steering based on its current postion and the its target /// </summary> /// <returns></returns> public Vector3 GetSteering() { _wanderTargetPosition = WanderTargetTransform.position; //get the jitter for this time frame var jitter = WanderJitter * Time.deltaTime; //add a small random vector to the target's position _wanderTargetPosition += new Vector3(Random.Range(-1f, 1f) * jitter, 0, Random.Range(-1f, 1f) * jitter); //make the wanderTarget fit on the wander circle again _wanderTargetPosition *= WanderRadius; //move the target in front of the character var targetPosition = transform.forward * WanderDistance + _wanderTargetPosition; // TODO this line is not optimal and should be only used for debugging Debug.DrawLine(transform.position, targetPosition); return(_seek.GetSteering(targetPosition)); }
public Steering Apply() { if (IsFinished()) { callback(true); } if (Time.frameCount % 1 == 0) { RequestPath(); } if (pathF.path != null) { return(pathF.GetSteering()); } else { return(Seek.GetSteering(target, agent, 50f)); //If path has not been solved yet just do Seek. } }
/// <summary> /// The Wander behavior. Will return a steering based on its current postion and the radius where it can wander /// </summary> /// <returns></returns> public Vector3 GetSteering() { var characterOrientation = transform.rotation.eulerAngles.y * Mathf.Deg2Rad; /* Update the wander orientation */ _wanderOrientation += RandomBinomial() * WanderRate; /* Calculate the combined target orientation */ var targetOrientation = _wanderOrientation + characterOrientation; /* Calculate the center of the wander circle */ var targetPosition = transform.position + OrientationToVector(characterOrientation) * WanderOffset; //debugRing.transform.position = targetPosition; /* Calculate the target position */ targetPosition = targetPosition + OrientationToVector(targetOrientation) * WanderRadius; //Debug.DrawLine (transform.position, targetPosition); return(_seek.GetSteering(targetPosition)); }
public static Steering GetSteering(Agent npc, float maxAccel, LayerMask layerMask, float obstacleMaxDist, float avoidDist, float whiskerSeparation, bool visibleRays = false) { Steering steering = new Steering(); Vector3 target = Vector3.zero; Vector3 leftRay = npc.position + npc.getRight() * whiskerSeparation / 2f; Vector3 rightRay = npc.position - npc.getRight() * whiskerSeparation / 2f; Vector3 centerRay = npc.position; AvoidanceRay[] rays = { new AvoidanceRay(leftRay, Util.RotateVector(npc.velocity.normalized, 30) * obstacleMaxDist / 2.2f), new AvoidanceRay(rightRay, Util.RotateVector(npc.velocity.normalized, -30) * obstacleMaxDist / 2.2f), new AvoidanceRay(centerRay, npc.velocity.normalized * obstacleMaxDist) }; RaycastHit hitInfo; bool rayHit = false; foreach (AvoidanceRay ray in rays) { if (Physics.Raycast(ray.startPoint, ray.direction, out hitInfo, ray.length, layerMask) && !rayHit) { target = hitInfo.normal * avoidDist + npc.position; //Errata, book proposes hitInfo.point instead of npc.position if (visibleRays) { Debug.DrawLine(ray.startPoint, hitInfo.point, Color.red); } rayHit = true; steering = Seek.GetSteering(target, npc, maxAccel, visibleRays); } else if (visibleRays) { Debug.DrawRay(ray.startPoint, ray.direction.normalized * ray.length, Color.yellow); } } return(steering); }
// Update is called once per frame void Update() { //Debug.Log(target); // Check distance to see if steering behavior should be applied to AI // float targetDist = (transform.position - target.transform.position).magnitude; // if (!DistanceActivation || targetDist >= activationRange) { } transform.position += linearVelocity * Time.deltaTime; // adding angular velocity to current transform rotation y component if (float.IsNaN(angularVelocity)) { angularVelocity = 0; } transform.eulerAngles += new Vector3(0, angularVelocity * Time.deltaTime, 0); // control to switch to proper steering behavior if (avoidObstacles) { ObstacleAvoidance avoid = new ObstacleAvoidance(); avoid.ai = this; SteeringOutput avoidForce = avoid.GetSteering(); if (avoidForce != null) { linearVelocity += avoidForce.linear; } } if (seperationObstacles.Length > 0) { Seperation seperation = new Seperation(); seperation.targets = seperationObstacles; seperation.ai = this; SteeringOutput seperateForce = seperation.GetSteering(); // check to see if steering is greater than zero and lock out control from other steering if (seperateForce.linear.magnitude > 0) { seperating = true; } else { seperating = false; } linearVelocity += seperateForce.linear * Time.deltaTime; } if (collisionAvoidance.Length > 0) { CollisionAvoidance avoidKinematic = new CollisionAvoidance(); avoidKinematic.ai = this; avoidKinematic.targets = collisionAvoidance; SteeringOutput avoidKinematicForce = avoidKinematic.GetSteering(); if (avoidKinematicForce != null) { linearVelocity += avoidKinematicForce.linear; } } switch (movementType) { case "seek": Seek mySeek = new Seek(); mySeek.ai = this; // if seek is false set seek property on class to false to activate flee mySeek.seek = true; mySeek.target = target; SteeringOutput steeringSeek = mySeek.GetSteering(); if (!seperating) { linearVelocity += steeringSeek.linear * Time.deltaTime; } if (linearVelocity.magnitude > maxSpeed) { linearVelocity.Normalize(); linearVelocity *= maxSpeed; } break; case "flee": Seek myFlee = new Seek(); myFlee.ai = this; // if seek is false set seek property on class to false to activate flee myFlee.seek = false; myFlee.target = target; SteeringOutput steeringFlee = myFlee.GetSteering(); if (!seperating) { linearVelocity += steeringFlee.linear * Time.deltaTime; } if (linearVelocity.magnitude > maxSpeed) { linearVelocity.Normalize(); linearVelocity *= maxSpeed; } break; case "arrive": Arrive myArrive = new Arrive(); myArrive.ai = this; myArrive.target = target; SteeringOutput steeringArrive = myArrive.GetSteering(); if (!seperating) { linearVelocity += steeringArrive.linear * Time.deltaTime; } break; case "pursue": Pursue myPursue = new Pursue(); myPursue.ai = this; myPursue.target = target; SteeringOutput steeringPursue = myPursue.GetSteering(); if (!seperating) { linearVelocity += steeringPursue.linear * Time.deltaTime; } if (linearVelocity.magnitude > maxSpeed) { linearVelocity.Normalize(); linearVelocity *= maxSpeed; } break; case "evade": Pursue myEvade = new Pursue(); myEvade.ai = this; myEvade.target = target; // This changes the seek flag in the parent Seek class of Pursue, sending it the flee vector instead myEvade.seek = false; SteeringOutput steeringEvade = myEvade.GetSteering(); if (!seperating) { linearVelocity += steeringEvade.linear * Time.deltaTime; } if (linearVelocity.magnitude > maxSpeed) { linearVelocity.Normalize(); linearVelocity *= maxSpeed; } break; default: // provide no input break; // If obstacles have been provided, return steering to seperate from them } switch (rotationType) { case "face": Face myFace = new Face(); myFace.ai = this; myFace.target = target; SteeringOutput steeringFace = myFace.GetSteering(); if (steeringFace != null) { // linearVelocity += steering.linear * Time.deltaTime; angularVelocity += steeringFace.angular * Time.deltaTime; } break; case "align": Align myAlign = new Align(); myAlign.ai = this; myAlign.target = target; SteeringOutput steeringAlign = myAlign.GetSteering(); if (steeringAlign != null) { //linearVelocity += steering.linear * Time.deltaTime; angularVelocity += steeringAlign.angular * Time.deltaTime; } break; case "look": LookWhereGoing myLook = new LookWhereGoing(); myLook.ai = this; myLook.target = target; SteeringOutput steeringLook = myLook.GetSteering(); if (steeringLook != null) { //linearVelocity += steering.linear * Time.deltaTime; angularVelocity += steeringLook.angular * Time.deltaTime; } break; default: //provide no input break; } }
// Update is called once per frame void Update() { transform.position += linearVelocity * Time.deltaTime; // adding angular velocity to current transform rotation y component if (float.IsNaN(angularVelocity)) { angularVelocity = 0; } transform.eulerAngles += new Vector3(0, angularVelocity * Time.deltaTime, 0); //dynamicSteering steering = new Seek(); // control to switch to proper steering behavior if (!arrive) { Seek mySeek = new Seek(); mySeek.ai = this; // if seek is false set seek property on class to false to activate flee if (!seek) { mySeek.seek = false; } else { mySeek.seek = true; } mySeek.target = target; SteeringOutput steering = mySeek.GetSteering(); linearVelocity += steering.linear * Time.deltaTime; angularVelocity += steering.angular * Time.deltaTime; if (linearVelocity.magnitude > maxSpeed) { linearVelocity.Normalize(); linearVelocity *= maxSpeed; } } else { Arrive myArrive = new Arrive(); myArrive.ai = this; myArrive.target = target; SteeringOutput steering = myArrive.GetSteering(); linearVelocity += steering.linear * Time.deltaTime; angularVelocity += steering.angular * Time.deltaTime; } if (align) { Align myAlign = new Align(); myAlign.ai = this; myAlign.target = target; SteeringOutput steering = myAlign.GetSteering(); if (steering != null) { linearVelocity += steering.linear * Time.deltaTime; angularVelocity += steering.angular * Time.deltaTime; } } if (lookWhereGoing && !align && !face) { LookWhereGoing myLook = new LookWhereGoing(); myLook.ai = this; myLook.target = target; SteeringOutput steering = myLook.GetSteering(); if (steering != null) { linearVelocity += steering.linear * Time.deltaTime; angularVelocity += steering.angular * Time.deltaTime; } else { Debug.Log("Returning Null"); } } if (!lookWhereGoing && !align && face) { Face myFace = new Face(); myFace.ai = this; myFace.target = target; SteeringOutput steering = myFace.GetSteering(); if (steering != null) { linearVelocity += steering.linear * Time.deltaTime; angularVelocity += steering.angular * Time.deltaTime; } } }
void Update() { SteeringOutput movementSteering; //SteeringOutput lookSteering; //Update position and rotation transform.position += linearVelocity * Time.deltaTime; Vector3 angularIncrement = new Vector3(0, angularVelocity * Time.deltaTime, 0); transform.eulerAngles += angularIncrement; switch (moveType) { case SteeringType.Pursue: movementSteering = pursueAI.GetSteering(); break; case SteeringType.Evade: movementSteering = evadeAI.GetSteering(); break; case SteeringType.FollowPath: movementSteering = followAI.GetSteering(); break; case SteeringType.Seek: movementSteering = seekAI.GetSteering(); break; case SteeringType.Flee: movementSteering = fleeAI.GetSteering(); break; case SteeringType.Seperation: movementSteering = seperationAI.GetSteering(); break; case SteeringType.Arrive: movementSteering = arriveAI.GetSteering(); break; case SteeringType.CollisionAvoidance: movementSteering = avoidAI.GetSteering(); break; case SteeringType.ObstacleAvoidance: movementSteering = obstacleAI.GetSteering(); break; default: movementSteering = new SteeringOutput(); break; } if (movementSteering != null) { linearVelocity += movementSteering.linear * Time.deltaTime; //angularVelocity += movementSteering.angular * Time.deltaTime; } switch (lookType) { case LookType.None: break; case LookType.Align: lookSteering = alignAI.GetSteering(); break; case LookType.Face: lookSteering = faceAI.GetSteering(); break; case LookType.LookWhereGoing: lookSteering = lookAI.GetSteering(); break; default: lookSteering = alignAI.GetSteering(); break; } if (lookSteering != null) { angularVelocity += lookSteering.angular * Time.deltaTime; } //Update kinematic reference with complex data it can't get by itself kinematic.GetData(movementSteering); kinematic.GetData(lookSteering); }