/// <summary> /// Update the behavior. /// </summary> /// <param name="manager">The steering manager.</param> /// <param name="actor">The actor being updated.</param> /// <param name="dt">The time since the last update, in seconds. /// </param> /// <returns>The steering object.</returns> public override Steering Update(SteeringManager manager, Actor actor, float dt) { if (target == null || !target.Alive) { return(Steering.zero); } Vector3 delta = Target.Position - actor.Position; Vector3 currentVel = actor.Velocity; if (manager.IsPlanar) { delta.y = 0f; currentVel.y = 0f; } float dist = delta.magnitude; if (dist > 0.0f) { float force = manager.MaxForce * (dist / arriveRadius); force = Mathf.Min(force, manager.MaxForce); delta *= force / dist; } return(new Steering(delta - currentVel, Vector3.zero)); }
/// <summary> /// Update the behavior. /// </summary> /// <param name="manager">The steering manager.</param> /// <param name="actor">The actor being updated.</param> /// <param name="dt">The time since the last update, in seconds. /// </param> /// <returns>The steering object.</returns> public override Steering Update(SteeringManager manager, Actor actor, float dt) { if (target == null || !target.Alive) { return Steering.zero; } Vector3 uVel = actor.Velocity; Vector3 uTargetVel = target.Velocity; Vector3 deltaPos = target.Position - actor.Position; Vector3 targetPos = target.Position; if(manager.IsPlanar) { uVel.y = 0f; uTargetVel.y = 0f; deltaPos.y = 0f; targetPos.y = 0f; } uVel.Normalize(); uTargetVel.Normalize(); float dv = Vector3.Dot(uVel, uTargetVel); if (Vector3.Dot(deltaPos, uVel) < 0f || dv > -0.93f) { Vector3 vel = uVel * manager.MaxForce; float combinedSpeed = (vel + target.Velocity).magnitude; if(combinedSpeed > 0f) { float predictionTime = deltaPos.magnitude / combinedSpeed; targetPos += target.Velocity * predictionTime; } } return new Steering(SteerToward(manager, actor, targetPos, dt), Vector3.zero); }
/// <summary> /// Update the behavior. /// </summary> /// <param name="manager">The steering manager.</param> /// <param name="actor">The actor being updated.</param> /// <param name="dt">The time since the last update, in seconds. /// </param> /// <returns>The steering object.</returns> public override Steering Update(SteeringManager manager, Actor actor, float dt) { Vector3 dir = actor.Forward; if(actor.Velocity.magnitude > velocityFaceThreshold) { dir = actor.Velocity / actor.Velocity.magnitude; } Vector3 delta = Quaternion.FromToRotation(actor.Forward, dir).eulerAngles; Vector3 angVel = actor.AngularVelocity; if(manager.IsPlanar) { angVel.x = 0f; delta.x = 0f; } else { delta.x = Mathf.DeltaAngle(0f, delta.x); } angVel.z = 0f; delta.z = 0.0f; delta.y = Mathf.DeltaAngle(0f, delta.y); float angDist = delta.magnitude; if(angDist > 0.0f) { float torque = manager.MaxTorque * (angDist / angleThreshold); torque = Mathf.Min(torque, manager.MaxTorque); delta *= torque / angDist; } return new Steering(Vector3.zero, delta - angVel); }
/// <summary> /// Update the behavior. /// </summary> /// <param name="manager">The steering manager.</param> /// <param name="actor">The actor being updated.</param> /// <param name="dt">The time since the last update, in seconds. /// </param> /// <returns>The steering object.</returns> public override Steering Update(SteeringManager manager, Actor actor, float dt) { if (target == null || !target.Alive) { return Steering.zero; } Vector3 delta = Target.Position - actor.Position; Vector3 currentVel = actor.Velocity; if(manager.IsPlanar) { delta.y = 0f; currentVel.y = 0f; } float dist = delta.magnitude; if (dist > 0.0f) { float force = manager.MaxForce * (dist / arriveRadius); force = Mathf.Min(force, manager.MaxForce); delta *= force / dist; } return new Steering(delta - currentVel, Vector3.zero); }
/// <summary> /// Update the behavior. /// </summary> /// <param name="manager">The steering manager.</param> /// <param name="actor">The actor being updated.</param> /// <param name="dt">The time since the last update, in seconds. /// </param> /// <returns>The steering object.</returns> public override Steering Update(SteeringManager manager, Actor actor, float dt) { Steering steering = Steering.zero; Vector3 forward = actor.Forward; forward.y = 0f; float size = (maxAngle * 2f) / (numRays - 1); float dHalf = (maxDistance - minDistance) * 0.5f; float dSize = (maxDistance - minDistance) / (numRays - 1); float totalWeight = 0f; Vector3 force = Vector3.zero; Vector3 torque = Vector3.zero; for (int i = 0; i < numRays; i++) { float angle = -maxAngle + i * size; float weight = 1f - Mathf.Abs(angle / maxAngle) * 0.25f; float dist = maxDistance - Mathf.Abs(-dHalf + i * dSize); Vector3 dir = Quaternion.AngleAxis(angle, Vector3.up) * forward; Debug.DrawLine(actor.Position, actor.Position + dir * dist, new Color(1f, 1f, 0f, weight)); RaycastHit hit; if (Physics.SphereCast(actor.Position, 5f, dir, out hit, dist, mask)) { float side = Vector3.Dot(hit.normal, actor.Right); Vector3 tangent = Vector3.zero; Vector3 half = Vector3.zero; if (side < 0f) // Normal is to the left { tangent = Vector3.Cross(actor.Up, hit.normal); half = tangent - actor.Right; } else // Normal is to the right { tangent = Vector3.Cross(hit.normal, actor.Up); half = actor.Right - tangent; } tangent.Normalize(); half.Normalize(); totalWeight += weight; float scale = 1f - hit.distance / maxDistance; Debug.DrawLine(hit.point, hit.point + tangent * manager.MaxForce * scale * weight, new Color(0f, 1f, 1f, scale)); Debug.DrawLine(hit.point, hit.point + half * manager.MaxForce * scale * weight, new Color(1f, 0f, 0f, scale)); lookTarget.Point = hit.point + tangent; torque += lookAt.Update(manager, actor, dt).Torque *scale *weight * 0.5f; force += half * manager.MaxForce * scale * weight; } } steering.Force = force / (totalWeight > 0f ? totalWeight : 1f); steering.Torque = torque; return(steering); }
/// <summary> /// Update the behavior. /// </summary> /// <param name="manager">The steering manager.</param> /// <param name="actor">The actor being updated.</param> /// <param name="dt">The time since the last update, in seconds. /// </param> /// <returns>The steering object.</returns> public override Steering Update(SteeringManager manager, Actor actor, float dt) { if (target == null || !target.Alive) { return(Steering.zero); } return(new Steering(SteerToward(manager, actor, target.Position, dt), Vector3.zero)); }
/// <summary> /// Update the behavior. /// </summary> /// <param name="manager">The steering manager.</param> /// <param name="actor">The actor being updated.</param> /// <param name="dt">The time since the last update, in seconds. /// </param> /// <returns>The steering object.</returns> public override Steering Update(SteeringManager manager, Actor actor, float dt) { if (target == null || !target.Alive) { return Steering.zero; } return new Steering(SteerToward(manager, actor, target.Position, dt), Vector3.zero); }
/// <summary> /// Update the behavior. /// </summary> /// <param name="manager">The steering manager.</param> /// <param name="actor">The actor being updated.</param> /// <param name="dt">The time since the last update, in seconds. /// </param> /// <returns>The steering object.</returns> public override Steering Update(SteeringManager manager, Actor actor, float dt) { float angle = Random.Range(-maxDeviation, maxDeviation); wanderAngle += angle; int radius = 200; Vector3 currPos = actor.Position; float x = currPos.x + radius * Mathf.Cos(wanderAngle); float z = currPos.z + radius * Mathf.Sin(wanderAngle); target.Point = new Vector3(x, currPos.y, z); return(base.Update(manager, actor, dt)); }
/// <summary> /// Steer away from the given point. /// </summary> /// <param name="actor">The actor for steering.</param> /// <param name="target">The target point.</param> /// <param name="dt">The delta time since the last call.</param> /// <returns></returns> protected Vector3 SteerAway(SteeringManager manager, Actor actor, Vector3 target, float dt) { Vector3 desired = actor.Position - target; if(manager.IsPlanar) { desired.y = 0f; } float dist = desired.magnitude; if (dist > 0.0f) { desired *= manager.MaxForce / dist; return desired - actor.Velocity; } return Vector3.zero; }
/// <summary> /// Steer away from the given point. /// </summary> /// <param name="actor">The actor for steering.</param> /// <param name="target">The target point.</param> /// <param name="dt">The delta time since the last call.</param> /// <returns></returns> protected Vector3 SteerAway(SteeringManager manager, Actor actor, Vector3 target, float dt) { Vector3 desired = actor.Position - target; if (manager.IsPlanar) { desired.y = 0f; } float dist = desired.magnitude; if (dist > 0.0f) { desired *= manager.MaxForce / dist; return(desired - actor.Velocity); } return(Vector3.zero); }
/// <summary> /// Update the behavior. /// </summary> /// <param name="manager">The steering manager.</param> /// <param name="actor">The actor being updated.</param> /// <param name="dt">The time since the last update, in seconds. /// </param> /// <returns>The steering object.</returns> public override Steering Update(SteeringManager manager, Actor actor, float dt) { if (target == null || !target.Alive) { return(Steering.zero); } Vector3 dir = target.Position - actor.Position; Vector3 facing = actor.Forward; dir.y = manager.IsPlanar ? 0f : dir.y; facing.y = manager.IsPlanar ? 0f : facing.y; Vector3 delta = Quaternion.FromToRotation(facing, dir).eulerAngles; Vector3 angVel = actor.AngularVelocity; if (manager.IsPlanar) { angVel.x = 0f; delta.x = 0f; } else { delta.x = Mathf.DeltaAngle(0f, delta.x); } angVel.z = 0f; delta.z = 0.0f; delta.y = Mathf.DeltaAngle(0f, delta.y); float angDist = delta.magnitude; if (angDist > 0.0f) { float torque = manager.MaxTorque * (angDist / angleThreshold); torque = Mathf.Min(torque, manager.MaxTorque); delta *= torque / angDist; } return(new Steering(Vector3.zero, delta - angVel)); }
/// <summary> /// Update the behavior. /// </summary> /// <param name="manager">The steering manager.</param> /// <param name="actor">The actor being updated.</param> /// <param name="dt">The time since the last update, in seconds. /// </param> /// <returns>The steering object.</returns> public override Steering Update(SteeringManager manager, Actor actor, float dt) { if (target == null || !target.Alive) { return(Steering.zero); } Vector3 uVel = actor.Velocity; Vector3 uTargetVel = target.Velocity; Vector3 deltaPos = target.Position - actor.Position; Vector3 targetPos = target.Position; if (manager.IsPlanar) { uVel.y = 0f; uTargetVel.y = 0f; deltaPos.y = 0f; targetPos.y = 0f; } uVel.Normalize(); uTargetVel.Normalize(); float dv = Vector3.Dot(uVel, uTargetVel); if (Vector3.Dot(deltaPos, uVel) < 0f || dv > -0.93f) { Vector3 vel = uVel * manager.MaxForce; float combinedSpeed = (vel + target.Velocity).magnitude; if (combinedSpeed > 0f) { float predictionTime = deltaPos.magnitude / combinedSpeed; targetPos += target.Velocity * predictionTime; } } return(new Steering(SteerToward(manager, actor, targetPos, dt), Vector3.zero)); }
/// <summary> /// Update the behavior. /// </summary> /// <param name="manager">The steering manager.</param> /// <param name="actor">The actor being updated.</param> /// <param name="dt">The time since the last update, in seconds. /// </param> /// <returns>The steering object.</returns> public override Steering Update(SteeringManager manager, Actor actor, float dt) { Vector3 dir = actor.Forward; if (actor.Velocity.magnitude > velocityFaceThreshold) { dir = actor.Velocity / actor.Velocity.magnitude; } Vector3 delta = Quaternion.FromToRotation(actor.Forward, dir).eulerAngles; Vector3 angVel = actor.AngularVelocity; if (manager.IsPlanar) { angVel.x = 0f; delta.x = 0f; } else { delta.x = Mathf.DeltaAngle(0f, delta.x); } angVel.z = 0f; delta.z = 0.0f; delta.y = Mathf.DeltaAngle(0f, delta.y); float angDist = delta.magnitude; if (angDist > 0.0f) { float torque = manager.MaxTorque * (angDist / angleThreshold); torque = Mathf.Min(torque, manager.MaxTorque); delta *= torque / angDist; } return(new Steering(Vector3.zero, delta - angVel)); }
/// <summary> /// Update the behavior. /// </summary> /// <param name="manager">The steering manager.</param> /// <param name="actor">The actor being updated.</param> /// <param name="dt">The time since the last update, in seconds. /// </param> /// <returns>The steering object.</returns> public override Steering Update(SteeringManager manager, Actor actor, float dt) { if (target == null || !target.Alive) { return Steering.zero; } Vector3 dir = target.Position - actor.Position; Vector3 facing = actor.Forward; dir.y = manager.IsPlanar ? 0f : dir.y; facing.y = manager.IsPlanar ? 0f : facing.y; Vector3 delta = Quaternion.FromToRotation(facing, dir).eulerAngles; Vector3 angVel = actor.AngularVelocity; if(manager.IsPlanar) { angVel.x = 0f; delta.x = 0f; } else { delta.x = Mathf.DeltaAngle(0f, delta.x); } angVel.z = 0f; delta.z = 0.0f; delta.y = Mathf.DeltaAngle(0f, delta.y); float angDist = delta.magnitude; if(angDist > 0.0f) { float torque = manager.MaxTorque * (angDist / angleThreshold); torque = Mathf.Min(torque, manager.MaxTorque); delta *= torque / angDist; } return new Steering(Vector3.zero, delta - angVel); }
/// <summary> /// Update the behavior. /// </summary> /// <param name="manager">The steering manager.</param> /// <param name="actor">The actor being updated.</param> /// <param name="dt">The time since the last update, in seconds. /// </param> /// <returns>The steering object.</returns> public override Steering Update(SteeringManager manager, Actor actor, float dt) { Steering steering = Steering.zero; Vector3 forward = actor.Forward; forward.y = 0f; float size = (maxAngle * 2f) / (numRays - 1); float dHalf = (maxDistance - minDistance) * 0.5f; float dSize = (maxDistance - minDistance) / (numRays - 1); float totalWeight = 0f; Vector3 force = Vector3.zero; Vector3 torque = Vector3.zero; for(int i = 0; i < numRays; i ++) { float angle = -maxAngle + i * size; float weight = 1f - Mathf.Abs(angle / maxAngle) * 0.25f; float dist = maxDistance - Mathf.Abs(-dHalf + i * dSize); Vector3 dir = Quaternion.AngleAxis(angle, Vector3.up) * forward; Debug.DrawLine(actor.Position, actor.Position + dir * dist, new Color(1f, 1f, 0f, weight)); Collider[] col = Physics.OverlapSphere(actor.Position + dir * dist * .5f, dist * .5f, mask); if(col.Length > 0) { RaycastHit hit; Ray r = new Ray (actor.Position, col[0].transform.position - actor.Position); col[0].Raycast (r, out hit, dist); float side = Vector3.Dot(hit.normal, actor.Right); Vector3 tangent = Vector3.zero; Vector3 half = Vector3.zero; if(side < 0f) { // Normal is to the left tangent = Vector3.Cross(actor.Up, hit.normal); half = tangent - actor.Right; } else { // Normal is to the right tangent = Vector3.Cross(hit.normal, actor.Up); half = actor.Right - tangent; } // tangent.Normalize(); // half.Normalize(); totalWeight += weight; float scale = 1f - hit.distance / maxDistance; Debug.DrawLine(hit.point, hit.point + tangent * manager.MaxForce * scale * weight, new Color(0f, 1f, 1f, scale)); Debug.DrawLine(hit.point, hit.point + half * manager.MaxForce * scale * weight, new Color(1f, 0f, 0f, scale)); lookTarget.Point = hit.point + tangent; torque += lookAt.Update(manager, actor, dt).Torque * scale * weight * 0.5f; force += half * manager.MaxForce * scale * weight; } } steering.Force = force / (totalWeight > 0f ? totalWeight : 1f); steering.Torque = torque; return steering; }
/// <summary> /// Update the behavior. /// </summary> /// <param name="manager">The steering manager.</param> /// <param name="actor">The actor being updated.</param> /// <param name="dt">The time since the last update, in seconds. /// </param> /// <returns>The steering object.</returns> public override Steering Update(SteeringManager manager, Actor actor, float dt) { float angle = Random.Range(-maxDeviation, maxDeviation); wanderAngle += angle; int radius = 200; Vector3 currPos = actor.Position; float x = currPos.x + radius * Mathf.Cos(wanderAngle); float z = currPos.z + radius * Mathf.Sin(wanderAngle); target.Point = new Vector3(x, currPos.y, z); return base.Update(manager, actor, dt); }
/// <summary> /// Update the behavior. /// </summary> /// <param name="actor">The actor being updated.</param> /// <param name="dt">The time since the last update, in seconds. /// </param> /// <returns>The steering object.</returns> public abstract Steering Update(SteeringManager manager, Actor actor, float dt);