public static void GetDividedCornersNonAlloc(this NavMeshPath navMeshPath, NavMeshQueryFilter filter, float distanceDivider, float yOffset, List <Vector3> outputPath, Vector3[] pathBuffer) { int count = navMeshPath.GetCornersNonAlloc(pathBuffer); navMeshPath.GetDividedCornersNonAlloc(filter, distanceDivider, yOffset, outputPath, pathBuffer, count); }
public void CheckPath() { if (start == null || end == null) { return; } NavMeshPath path = new NavMeshPath(); NavMesh.CalculatePath(start.position, end.position, NavMesh.AllAreas, path); PathClear(); switch (path.status) { case NavMeshPathStatus.PathComplete: case NavMeshPathStatus.PathPartial: var count = path.GetCornersNonAlloc(points); SetPaths(count, points); break; case NavMeshPathStatus.PathInvalid: Debug.Log("PathInvalid"); break; } }
/// <summary> /// Looks for a position to investigate in given direction. /// </summary> public static bool FindNewThreatPositionInDirection(Vector3 direction, AIController controller, ref AISituation situation, NavMeshAgent agent) { var corners = new Vector3[32]; float extra = 0f; while (extra < 20f) { var p = situation.CurrentPosition + direction * (controller.Distances.MinSearch + extra); var path = new NavMeshPath(); agent.CalculatePath(p, path); if (path.status != NavMeshPathStatus.PathInvalid) { int count = path.GetCornersNonAlloc(corners); if (count > 1) { situation.ThreatGroundPosition = corners[count - 1]; return(true); } } extra += 1f; } return(false); }
private void HandleCharacterNavigation() { if (NavMesh.CalculatePath(Character.transform.position, Destination.position, NavMesh.AllAreas, _path)) { _lastValidDestination = Destination.position; } else { NavMesh.CalculatePath(Character.transform.position, _lastValidDestination, NavMesh.AllAreas, _path); } AICharacterInputs characterInputs = new AICharacterInputs(); int cornersCount = _path.GetCornersNonAlloc(_pathCorners); if (cornersCount > 1) { // Build the CharacterInputs struct characterInputs.MoveVector = (_pathCorners[1] - Character.transform.position).normalized; // Apply inputs to character Character.SetInputs(ref characterInputs); } else { // Build the CharacterInputs struct characterInputs.MoveVector = Vector3.zero; // Apply inputs to character Character.SetInputs(ref characterInputs); } }
public static Vector3 GetNavPoint(Vector3 current, Vector3 target, float range, int area, out int count, Vector3[] points) { Vector3 tgt = target; var random = MovementDictionary.RandomCount; for (var i = 0; i < random; i++) { path.ClearCorners(); if (NavMesh.CalculatePath(current, tgt, area, path)) { if (points != null) { count = path.GetCornersNonAlloc(points); } else { count = 0; } return(tgt); } var circle = UnityEngine.Random.insideUnitCircle; tgt += new Vector3(circle.x, 0, circle.y) * range; } count = 0; return(current); }
/// <summary> /// Sets up the navigation agent to move to the givent position. /// </summary> private void updatePath() { AIUtil.Path(ref _path, transform.position, _target); _pathLength = _path.GetCornersNonAlloc(_pathPoints); _currentPathIndex = 0; if (_pathLength > _pathPoints.Length) { _pathLength = _pathPoints.Length; } if (_pathLength > 1) { var vector = _pathPoints[1] - _pathPoints[0]; var distance = vector.magnitude; if (distance > 0.3f) { updateDirection(vector / distance, true); } } _hasCheckedIfReachable = false; _positionToCheckIfReachable = _target; }
static int GetCornersNonAlloc(IntPtr L) { LuaScriptMgr.CheckArgsCount(L, 2); NavMeshPath obj = LuaScriptMgr.GetNetObject <NavMeshPath>(L, 1); Vector3[] objs0 = LuaScriptMgr.GetArrayObject <Vector3>(L, 2); int o = obj.GetCornersNonAlloc(objs0); LuaScriptMgr.Push(L, o); return(1); }
/// <summary> /// Sets up the navigation agent to move to the givent position. /// </summary> private void updatePath() { AIUtil.Path(ref _path, transform.position, _target); _pathLength = _path.GetCornersNonAlloc(_pathPoints); _currentPathIndex = 0; if (_pathLength > 1) { updateDirection((_pathPoints[1] - _pathPoints[0]).normalized, true); } }
public static float CalculateDistance(this NavMeshPath path, Vector3[] corners, out int cornerCount) { float distance = 0f; cornerCount = path.GetCornersNonAlloc(corners); for (int i = 1; i < cornerCount; i++) { distance += Vector3.Distance(corners[i - 1], corners[i]); } return(distance); }
private IEnumerator Run(float initialProgress) { var fixedUpdateWait = new WaitForFixedUpdate(); Vector3[] corner = new Vector3[path.corners.Length]; path.GetCornersNonAlloc(corner); var length = getLength(path); float progress = initialProgress; float breakProgress = 0; bool searchingPath = false; bool waitingForSun = false; var tempLook = lookTarget; while (progress < length - 1) { yield return(fixedUpdateWait); progress += myAgent.speed * Time.fixedDeltaTime; var movement = Vector3.ClampMagnitude(sample(corner, progress) - transform.position, myAgent.speed * Time.fixedDeltaTime * gameTime.PlayTime); myAgent.Move(Vector3.ClampMagnitude(movement, length - progress)); Vector3 direction = (lookTarget - transform.position).normalized; Quaternion lookRotation = Quaternion.LookRotation(direction); transform.rotation = Quaternion.RotateTowards(transform.rotation, lookRotation, RotationSpeed); if (progress >= RecalcThreshold) { if (!myAgent.pathPending) { if (!searchingPath) { searchingPath = true; breakProgress = progress; StartCoroutine(getPath(player.position)); } else if (!waitingForSun) { waitingForSun = true; StartCoroutine(calcSun()); } else if (!calculatingSun) { run = StartCoroutine(Run(0)); yield break; } } } } StartCoroutine(agentFollow()); }
public void GetPathTowards(Vector3 Destination) { path = new NavMeshPath(); path.ClearCorners(); agent.CalculatePath(GetClosestPointToNavMesh(Destination), path); if (path == null || path.status == NavMeshPathStatus.PathInvalid) { Debug.LogError("No path found."); return; } path.GetCornersNonAlloc(Path); }
public static NavMeshPath DeserializeNavPath(SerializedVector3[] sPathCorners) { NavMeshPath path = new NavMeshPath(); Vector3[] pathCorners = new Vector3[sPathCorners.Length]; for (int i = 0; i < pathCorners.Length; i++) { pathCorners[i] = DeserializeVector3(sPathCorners[i]); } path.GetCornersNonAlloc(pathCorners); return(path); }
private void MoveDestination(MoveTarget moveTarget, ActorAI actor) { float pas = this.currentSpeedLevel * RandomSpeedFactor * Time.deltaTime; Vector3 destination = Vector3.zero; switch (moveTarget) { case MoveTarget.Item: destination = ItemTargetDestination; break; case MoveTarget.Map: destination = MapDestination; break; case MoveTarget.Opponent: destination = OpponentTargetDestination; break; default: break; } destination.y = FloorYOffset; NavMeshPath path = new NavMeshPath(); NavMesh.CalculatePath(actor.transform.position, destination, NavMesh.AllAreas, path); Vector3[] pathpoints; if (path.status == NavMeshPathStatus.PathComplete) { pathpoints = new Vector3[path.corners.Length]; int nbr = path.GetCornersNonAlloc(pathpoints); if (nbr > PathVectorIndex) { destination = pathpoints[PathVectorIndex]; } } destination.y = FloorYOffset; Vector3 nouvellePosition = Vector3.MoveTowards(actor.transform.position, destination, pas); Vector3 mouvement = new Vector3(nouvellePosition.x - actor.transform.position.x, nouvellePosition.y - actor.transform.position.y, nouvellePosition.z - actor.transform.position.z); float angle = Mathf.Atan2(mouvement.x, mouvement.z) * Mathf.Rad2Deg; actor.transform.position = nouvellePosition; actor.transform.rotation = Quaternion.AngleAxis(angle, Vector3.up); }
private void OnGUI() { if (debugInfo) { var cam = Camera.main; if (cam == null) { return; } Vector2 size = Vector2.zero; int index = 1; var agentHasPathContent = new GUIContent("Is Agent Moving: " + agent.hasPath.ToString()); size = new GUIStyle(GUI.skin.label).CalcSize(agentHasPathContent); GUI.Label(new Rect(5f, 5f + (size.y * index), size.x, size.y), agentHasPathContent); index++; var isMovingContent = new GUIContent("Has Reached Destination: " + HasReachedDestination().ToString()); size = new GUIStyle(GUI.skin.label).CalcSize(isMovingContent); GUI.Label(new Rect(5f, 5f + (size.y * index), size.x, size.y), isMovingContent); index++; var getRemainingDistanceContent = new GUIContent("Remaining Distance: " + GetDistanceRemaining().ToString()); size = new GUIStyle(GUI.skin.label).CalcSize(getRemainingDistanceContent); GUI.Label(new Rect(5f, 5f + (size.y * index), size.x, size.y), getRemainingDistanceContent); index++; var agentAccelerationContent = new GUIContent("Acceleration: " + agent.acceleration.ToString()); size = new GUIStyle(GUI.skin.label).CalcSize(agentAccelerationContent); GUI.Label(new Rect(5f, 5f + (size.y * index), size.x, size.y), agentAccelerationContent); index++; var speedContent = new GUIContent("Speed: " + agent.speed.ToString()); size = new GUIStyle(GUI.skin.label).CalcSize(speedContent); GUI.Label(new Rect(5f, 5f + (size.y * index), size.x, size.y), speedContent); index++; if (path != null) { var turnAngleContent = new GUIContent("Number Of Corners: " + path.GetCornersNonAlloc(path.corners).ToString()); size = new GUIStyle(GUI.skin.label).CalcSize(turnAngleContent); GUI.Label(new Rect(5f, 5f + (size.y * index), size.x, size.y), turnAngleContent); index++; } } }
private void HandleCharacterNavigation() { AICharacterInputs aiCharacterInputs = new AICharacterInputs(); if ((character.transform.position - destination).magnitude <= 0.2f) { aiCharacterInputs.MoveVector = Vector3.zero; // Apply inputs to character character.SetInputs(ref aiCharacterInputs); return; } if (NavMesh.CalculatePath(character.transform.position, destination, NavMesh.AllAreas, _path)) { _lastValidDestination = destination; } else { NavMesh.CalculatePath(character.transform.position, _lastValidDestination, NavMesh.AllAreas, _path); } int cornersCount = _path.GetCornersNonAlloc(_pathCorners); //Calculate path corners if (cornersCount >= 1) { // Build the CharacterInputs struct aiCharacterInputs.MoveVector = (_pathCorners[1] - character.transform.position).normalized; // Apply inputs to character character.SetInputs(ref aiCharacterInputs); } else { // Build the CharacterInputs struct aiCharacterInputs.MoveVector = Vector3.zero; // Apply inputs to character character.SetInputs(ref aiCharacterInputs); } }
/// <summary> /// Updates the target situation to approach an enemy that's in cover. /// </summary> public static void ApproachACovered(AIController controller, ref AISituation situation) { var path = new NavMeshPath(); var corners = new Vector3[16]; var resultPosition = situation.ThreatGroundPosition; var resultDistance = 9999f; var coverAngle = Util.AngleOfVector(situation.ThreatCoverForward); for (int a = 0; a < 18; a++) { var angle = coverAngle - 180f + a * 10; var position = situation.ThreatGroundPosition + new Vector3(Mathf.Cos(angle * Mathf.Deg2Rad), 0, Mathf.Sin(angle * Mathf.Deg2Rad)) * controller.Distances.MinEnemy; NavMeshHit hit; if (NavMesh.SamplePosition(position, out hit, 1.0f, NavMesh.AllAreas) && AIUtil.IsInSight(controller, hit.position, situation.ThreatStandingTopPosition)) { NavMesh.CalculatePath(controller.transform.position, hit.position, NavMesh.AllAreas, path); if (path.status == NavMeshPathStatus.PathComplete && !AIUtil.IsPositionTooCloseToFriends(controller, hit.position)) { var dist = 0f; for (int i = 1; i < path.GetCornersNonAlloc(corners); i++) { dist += Vector3.Distance(corners[i - 1], corners[i]); } if (dist < resultDistance) { resultDistance = dist; resultPosition = position; } } } } situation.TargetPosition = resultPosition; situation.TargetCover = null; }
private bool ExtendPlayerPath(Vector3 targetPosition) { Vector3 currentPosition = WorldPositionPath.Last != null ? WorldPositionPath.Last.Value : WorldPosition; float targetDistance = Vector3.Distance(currentPosition, targetPosition); if (WorldPositionPath.Count < minPathNodes || targetDistance >= minPathNodeDistance) { agent.Warp(currentPosition); agent.CalculatePath(targetPosition, path); agent.Warp(targetPosition); pathCornerCount = path.GetCornersNonAlloc(pathCorners); for (int i = 0; i < pathCornerCount; i++) { WorldPositionPath.AddLast(pathCorners[i]); } return(true); } return(false); }
private float GetDistance(NavMeshPath path) { var cornersBuffer = ArrayPool <Vector3> .Shared.Rent(MaxCorners); try { var cornersCount = path.GetCornersNonAlloc(cornersBuffer); float distance = 0; if (cornersCount > 1) { for (var cornerIndex = 1; cornerIndex < cornersCount; cornerIndex++) { distance += Vector3.Distance(cornersBuffer[cornerIndex - 1], cornersBuffer[cornerIndex]); } } return(distance); } finally { ArrayPool <Vector3> .Shared.Return(cornersBuffer); } }
public override void findPath(int moveType, SList <PosData> list, PosData from, PosData target) { list.clear(); //有路径 if (NavMesh.CalculatePath(from.getVector(), target.getVector(), BaseC.constlist.mapMoveType_getMask(moveType), _navMeshPath)) { Vector3[] corners = _corners; var len = _navMeshPath.GetCornersNonAlloc(corners); PosData p; if (len > 0) { //跳过起始点 for (int i = 1; i < len; i++) { p = new PosData(); p.setByVector(corners[i]); list.add(p); } } } }
void Start() { path = new NavMeshPath(); NavMesh.CalculatePath(start.localPosition, goal.localPosition, NavMesh.AllAreas, path); path.GetCornersNonAlloc(positions); }
private bool isValidCover(Cover cover, Vector3 position, int direction, bool checkPath, bool avoidPivot = true) { if (cover == _unreachableCover) { return(false); } if (_isKeepingCloseTo && Vector3.Distance(position, _keepCloseTo.Position) > _keepCloseTo.Distance) { return(false); } if (!_hasPivot) { if (!AIUtil.IsCoverPositionFree(cover, position, 1, _actor)) { return(false); } return(true); } if (!_hasCachedEnemies) { _cachedEnemyCount = 0; _hasCachedEnemies = true; var totalActorCount = AIUtil.FindActors(position, MinDefenselessDistance, _actor); if (totalActorCount > 0) { var enemyCount = 0; for (int i = 0; i < totalActorCount; i++) { if (AIUtil.Actors[i].Side != _actor.Side) { enemyCount++; } } if (enemyCount > 0) { if (_cachedEnemies == null || _cachedEnemies.Length < enemyCount) { _cachedEnemies = new Actor[enemyCount]; } var index = 0; for (int i = 0; i < totalActorCount; i++) { if (AIUtil.Actors[i].Side != _actor.Side) { _cachedEnemies[index++] = AIUtil.Actors[i]; } } _cachedEnemyCount = index; } } } for (int i = 0; i < _cachedEnemyCount; i++) { var enemy = _cachedEnemies[i]; if (enemy.Side != _actor.Side) { var enemyPosition = enemy.transform.position; var distance = Vector3.Distance(position, enemyPosition); if (distance < AvoidDistance) { return(false); } if (!AIUtil.IsGoodAngle(MaxTallCoverThreatAngle, MaxLowCoverThreatAngle, cover, position, enemyPosition, cover.IsTall)) { return(false); } } } if (_isPivotThreat) { var distance = Vector3.Distance(position, _pivotPosition); if (_hasMaxPivotDistance && distance > _maxPivotDistance) { return(false); } var aimPosition = position; if (AIUtil.IsObstructed(aimPosition + (_actor.StandingTopPosition - transform.position), _pivotPosition + Vector3.up * 2)) { return(false); } } else { var distance = Vector3.Distance(position, _pivotPosition); if (_hasMaxPivotDistance && distance > _maxPivotDistance) { return(false); } if (!AIUtil.IsGoodAngle(MaxDefenseAngle, MaxDefenseAngle, cover, _pivotPosition, position, cover.IsTall)) { return(false); } } if (!AIUtil.IsCoverPositionFree(cover, position, 1, _actor)) { return(false); } if (checkPath) { if (NavMesh.CalculatePath(transform.position, position, 1, _path)) { if (avoidPivot) { var count = _path.GetCornersNonAlloc(_corners); for (int i = 0; i < count; i++) { var a = i == 0 ? transform.position : _corners[i - 1]; var b = _corners[i]; var closest = Util.FindClosestToPath(a, b, _pivotPosition); if (Vector3.Distance(closest, _pivotPosition) < AvoidDistance) { return(false); } } } } else { return(false); } } return(true); }
/// <summary> /// Updates the target situation to approach an enemy that's not in cover. /// </summary> public static void ApproachAFree(AIController controller, ref AISituation situation, NavMeshAgent agent, float maxDistance, bool approachStanding) { situation.TargetCover = null; situation.TargetPosition = situation.ThreatGroundPosition; var path = new NavMeshPath(); agent.CalculatePath(situation.ThreatGroundPosition, path); var corners = new Vector3[16]; var count = path.GetCornersNonAlloc(corners); if (count < 2) { return; } var i = 0; var p0 = corners[i]; var p1 = corners[i + 1]; var f = 1f; var targetPosition = approachStanding ? situation.ThreatStandingTopPosition : situation.ThreatGroundPosition; { var distLeft = Vector3.Distance(controller.transform.position, situation.ThreatGroundPosition); while (distLeft > maxDistance) { var pd = Vector3.Distance(p0, p1); var left = distLeft - maxDistance; distLeft -= pd; if (pd >= left) { f = left / pd; break; } else { i++; if (i + 1 >= count) { i = 0; break; } else { p0 = corners[i]; p1 = corners[i + 1]; } } } } while (i + 1 < count) { var p = p0 + (p1 - p0) * f; if (AIUtil.IsInSight(controller, p, targetPosition)) { situation.TargetPosition = p; break; } f += 0.2f; if (f >= 1f) { if (AIUtil.IsInSight(controller, p1, targetPosition)) { situation.TargetPosition = p1; break; } f = 0; i++; } } }
/// <summary> /// Updates the target situation to take cover. Returns true if a cover was found. /// </summary> public static bool TakeCover(AIController controller, ref AISituation situation) { var currentVectorToTarget = situation.ThreatGroundPosition - situation.CurrentPosition; var currentDistanceToTarget = currentVectorToTarget.magnitude; Cover result = null; float resultPathDistance = 0; int resultDirection = 0; Vector3 resultPosition = situation.CurrentPosition; var path = new NavMeshPath(); var corners = new Vector3[32]; var isAlreadyTooClose = currentDistanceToTarget <= controller.Distances.MinEnemy || currentDistanceToTarget <= controller.Cover.MinCoverToEnemyDistance; var covers = new List <CoverItem>(); foreach (var collider in Physics.OverlapSphere(controller.transform.position, controller.Cover.MaxDistance, 0x1 << 8, QueryTriggerInteraction.Collide)) { if (!collider.isTrigger) { continue; } var cover = CoverSearch.GetCover(collider.gameObject); if (cover == null || cover == situation.CurrentCover) { continue; } var item = new CoverItem(); item.Cover = cover; item.IsTall = cover.IsTall(controller.Motor.CoverSettings.TallThreshold); if (item.IsTall) { item.Direction = cover.ClosestCornerTo(situation.CurrentPosition, controller.Motor.CoverSettings.CornerAimTriggerDistance, out item.Point); } else { item.Point = cover.ClosestPointTo(situation.CurrentPosition, controller.Motor.CoverSettings.LowSideEnterRadius, 0.3f); } if (float.IsNaN(item.Point.x) || float.IsNaN(item.Point.z)) { continue; } item.Point.y = cover.Bottom; item.Distance = Vector3.Distance(controller.transform.position, item.Point); covers.Add(item); } foreach (var item in covers.OrderBy(o => o.Distance)) { var isTall = item.IsTall; var cover = item.Cover; var point = item.Point; var coverDirection = item.Direction; if (!AIUtil.IsGoodAngle(controller, cover, point, situation.ThreatGroundPosition, isTall)) { continue; } var distanceToTarget = Vector3.Distance(situation.ThreatGroundPosition, point); if (distanceToTarget < controller.Distances.MinEnemy || distanceToTarget < controller.Cover.MinCoverToEnemyDistance) { continue; } if (situation.CurrentCover != null && Vector3.Distance(situation.CurrentPosition, point) < controller.Cover.MinSwitchDistance) { continue; } if ((controller.Health == null || controller.Health.Health > controller.Fighting.MinHealth)) { if (isTall) { Vector3 aimPoint; coverDirection = cover.ClosestCornerTo(point, -controller.Motor.CoverSettings.CornerOffset.x, out aimPoint); if (!AIUtil.IsInSight(controller, aimPoint, situation.ThreatStandingTopPosition)) { continue; } } else if (!AIUtil.IsInSight(controller, point, situation.ThreatStandingTopPosition)) { continue; } } var distanceToOrigin = Vector3.Distance(situation.CurrentPosition, point); if (situation.CurrentCover == null) { if (distanceToOrigin > controller.Cover.MaxDistance) { continue; } } else if (distanceToOrigin > controller.Cover.MaxSwitchDistance) { continue; } var areThereFriends = false; { var hasChangedPosition = false; Vector3 side; if (Vector3.Dot((point - situation.CurrentPosition).normalized, cover.Right) > 0) { side = cover.Right; } else { side = cover.Left; } do { hasChangedPosition = false; if (AIUtil.IsCoverPositionTooCloseToFriends(cover, controller, point)) { var next = point + side * 0.5f; if (cover.IsInFront(next, false)) { point = next; hasChangedPosition = true; } else { areThereFriends = true; } } }while (hasChangedPosition); } if (areThereFriends) { continue; } var isOk = false; NavMesh.CalculatePath(situation.CurrentPosition, point, NavMesh.AllAreas, path); float pathDistance = 0f; var count = path.GetCornersNonAlloc(corners); if (count < 2) { continue; } var isTooCloseToEnemy = false; for (int i = 1; i < count; i++) { pathDistance += Vector3.Distance(corners[i - 1], corners[i]); if (!isAlreadyTooClose) { if (Util.DistanceToSegment(situation.ThreatGroundPosition, corners[i - 1], corners[i]) <= controller.Distances.MinPassing) { isTooCloseToEnemy = true; break; } } } if (isTooCloseToEnemy) { continue; } if (situation.CurrentCover == null) { isOk = result == null || pathDistance < resultPathDistance; } else if (controller.Health == null || controller.Health.Health > controller.Fighting.MinHealth) { isOk = (isAlreadyTooClose || distanceToTarget < currentDistanceToTarget) && (result == null || pathDistance < resultPathDistance); } else { isOk = distanceToTarget > currentDistanceToTarget && (result == null || pathDistance < resultPathDistance); } if (isOk) { result = cover; resultPosition = point; resultPathDistance = pathDistance; resultDirection = coverDirection; break; } } situation.TargetDirection = resultDirection; if (result == null) { if (situation.IsThreatInCover) { ApproachACovered(controller, ref situation); } else { ApproachAFree(controller, ref situation, controller.Agent, controller.Distances.MaxWalkingFight, true); } return(false); } else { situation.IsNewCover = true; situation.TargetCover = result; situation.TargetPosition = resultPosition; return(true); } }
// Attempts to find a nearby place that the target can't see us at. // Returns true if one was found; if it was, put the position in the // hidingSpot variable. bool FindHidingSpot(out Vector3 hidingSpot) { var distribution = new PoissonDiscSampler( searchAreaSize, searchAreaSize, searchCellSize); var candidateHidingSpots = new List <Vector3>(); foreach (var point in distribution.Samples()) { var searchPoint = point; // Re-position the point so that the middle of the search area // is at (0,0) searchPoint.x -= searchAreaSize / 2f; searchPoint.y -= searchAreaSize / 2f; var searchPointLocalSpace = new Vector3( searchPoint.x, transform.localPosition.y, searchPoint.y ); // Can they see us from here? var searchPointWorldSpace = transform.TransformPoint(searchPointLocalSpace); // Find the nearest point on the navmesh NavMeshHit hit; bool foundPoint; foundPoint = NavMesh.SamplePosition( searchPointWorldSpace, out hit, 5, NavMesh.AllAreas ); if (foundPoint == false) { // We can't get here. Disregard as a place to hide. continue; } searchPointWorldSpace = hit.position; var canSee = visibility.CheckVisibilityToPoint(searchPointWorldSpace); if (canSee == false) { // we can't see the target from this position. return it! candidateHidingSpots.Add(searchPointWorldSpace); } if (visualize) { Color debugColor = canSee ? Color.red : Color.green; Debug.DrawLine( transform.position, searchPointWorldSpace, debugColor, 0.1f); } } if (candidateHidingSpots.Count == 0) { // We didn't find a hiding spot. // Provide a dummy value hidingSpot = Vector3.zero; // Indicate our failure return(false); } // For each of our candidate points, calculate the length of the // path needed to reach it. // Build a list of candidate points, matched with the length of the // path needed to reach it. List <KeyValuePair <Vector3, float> > paths; // For each point, calculate the length paths = candidateHidingSpots.ConvertAll( (Vector3 point) => { // Create a new path that reaches this point var path = new NavMeshPath(); agent.CalculatePath(point, path); // Store the distance needed for this path float distance; if (path.status != NavMeshPathStatus.PathComplete) { // If this path doesn't reach the target, consider it // infinitely far away distance = Mathf.Infinity; } else { // Get up to 32 of the points on this path var corners = new Vector3[32]; var cornerCount = path.GetCornersNonAlloc(corners); // Start with the first point Vector3 current = corners[0]; distance = 0; // Figure out the cumulative distance for each point for (int c = 1; c < cornerCount; c++) { var next = corners[c]; distance += Vector3.Distance(current, next); current = next; } } // Build the pair of point and distance return(new KeyValuePair <Vector3, float>(point, distance)); }); // Sort this list based on distance, so that the shortest path is // at the front of the list paths.Sort((a, b) => { return(a.Value.CompareTo(b.Value)); }); // Return the point that's the shortest to reach hidingSpot = paths[0].Key; return(true); }
/// <summary> /// Told by the brains to investigate a position. /// </summary> /// <param name="position"></param> public void ToInvestigatePosition(Vector3 position) { _isInvestigating = true; _position = position; _cover = null; var minDistance = 0f; for (int i = 0; i < Physics.OverlapSphereNonAlloc(position, CoverSearchDistance, _colliders, 0x1 << 8, QueryTriggerInteraction.Collide); i++) { var cover = CoverSearch.GetCover(_colliders[i].gameObject); if (cover != null) { var point = cover.ClosestPointTo(position, 0.3f, 0.3f); var distance = Vector3.Distance(position, point); if (distance < minDistance || _cover == null) { _cover = cover; _position = point; minDistance = distance; } } } _verifyDistance = Util.GetViewDistance(_position, VerifyDistance, true); if (_cover == null) { _hasReachedCoverLine = false; if (isActiveAndEnabled) { Message("ToWalkTo", position); Message("OnInvestigationStart"); } } else { var vector = _position - transform.position; _hasReachedCoverLine = Vector3.Dot(_cover.Forward, vector) > 0; if (_hasReachedCoverLine) { if (isActiveAndEnabled) { Message("ToWalkTo", _position); Message("OnInvestigationStart"); } } else { var left = _cover.LeftCorner(_cover.Bottom, CoverOffset) - _cover.Forward * 1.0f; var right = _cover.RightCorner(_cover.Bottom, CoverOffset) - _cover.Forward * 1.0f; AIUtil.Path(ref _path, transform.position, left); var leftLength = 0f; if (_path.status == NavMeshPathStatus.PathInvalid) { leftLength = 999999f; } else { for (int i = 1; i < _path.GetCornersNonAlloc(_corners); i++) { leftLength += Vector3.Distance(_corners[i], _corners[i - 1]); } } AIUtil.Path(ref _path, transform.position, right); var rightLength = 0f; if (_path.status == NavMeshPathStatus.PathInvalid) { rightLength = 999999f; } else { for (int i = 1; i < _path.GetCornersNonAlloc(_corners); i++) { rightLength += Vector3.Distance(_corners[i], _corners[i - 1]); } } if (leftLength < rightLength) { _approachPosition = left; } else { _approachPosition = right; } var distance = Vector3.Distance(_approachPosition, _position); if (distance + VerifyRadius > _verifyDistance) { _approachPosition = _position + Vector3.Normalize(_approachPosition - _position) * (_verifyDistance + VerifyRadius - 0.1f); } if (isActiveAndEnabled) { Message("ToWalkTo", _approachPosition); Message("OnInvestigationStart"); } } } }
private void findNewFleePosition(bool isAlreadyTooClose) { var targetPosition = transform.position; var targetDot = -10f; var fromThreat = transform.position - _threatPosition; fromThreat.y = 0; fromThreat.Normalize(); FleeZone targetBlock = null; foreach (var block in FleeZone.All) { var position = block.transform.position; position.y = block.Bottom; if (Vector3.Distance(position, _threatPosition) < AvoidDistance) { continue; } if (block == _targetBlock) { continue; } var dot = -1f; if (NavMesh.CalculatePath(transform.position, position, 1, _path)) { var count = _path.GetCornersNonAlloc(_corners); if (count < 1) { continue; } if (!isAlreadyTooClose) { var isOk = true; for (int i = 0; i < count; i++) { var a = i == 0 ? transform.position : _corners[i - 1]; var b = _corners[i]; var closest = Util.FindClosestToPath(a, b, _threatPosition); if (Vector3.Distance(closest, _threatPosition) < AvoidDistance) { isOk = false; break; } } if (!isOk) { continue; } } var first = _corners[0]; if (count > 1) { first = _corners[1]; } var vector = first - transform.position; vector.y = 0; vector.Normalize(); dot = Vector3.Dot(vector, fromThreat) * Vector3.Distance(position, transform.position); } else { continue; } if (dot > targetDot) { targetDot = dot; targetPosition = position + (-block.Width * 0.5f + Random.Range(0f, block.Width)) * block.transform.right + (-block.Depth * 0.5f + Random.Range(0f, block.Depth)) * block.transform.forward; targetBlock = block; } } _targetBlock = targetBlock; _targetPosition = targetPosition; Message("ToSprintTo", targetPosition); Message("ToFaceWalkDirection", targetPosition); }
private bool isValidCover(Cover cover, Vector3 position, int direction, bool checkPath) { if (!_hasThreat) { return(true); } if (Vector3.Distance(position, _threatPosition) < AvoidDistance) { return(false); } if (!AIUtil.IsGoodAngle(MaxTallCoverAngle, MaxLowCoverAngle, cover, position, _threatPosition, cover.IsTall)) { return(false); } if (!AIUtil.IsCoverPositionFree(cover, position, 1, _actor)) { return(false); } var aimPosition = position; if (cover.IsTall) { var angle = Util.AngleOfVector(_threatPosition - position); if (direction > 0) { if (!cover.IsFrontField(angle, _motor.CoverSettings.Angles.TallRightCornerFront)) { return(false); } if (!cover.IsRight(angle, _motor.CoverSettings.Angles.RightCorner, false)) { return(false); } aimPosition = cover.RightCorner(cover.Bottom, _motor.CoverSettings.CornerOffset.x); } else if (direction < 0) { if (!cover.IsFrontField(angle, _motor.CoverSettings.Angles.TallLeftCornerFront)) { return(false); } if (!cover.IsLeft(angle, _motor.CoverSettings.Angles.LeftCorner, false)) { return(false); } aimPosition = cover.LeftCorner(cover.Bottom, _motor.CoverSettings.CornerOffset.x); } } if (AIUtil.IsObstructed(aimPosition + (_actor.StandingTopPosition - transform.position), _threatPosition + Vector3.up * 2, 100)) { return(false); } if (checkPath) { if (Vector3.Distance(transform.position, _threatPosition) > AvoidDistance) { if (NavMesh.CalculatePath(transform.position, position, 1, _path)) { for (int i = 0; i < _path.GetCornersNonAlloc(_corners); i++) { var a = i == 0 ? transform.position : _corners[i - 1]; var b = _corners[i]; var closest = Util.FindClosestToPath(a, b, _threatPosition); if (Vector3.Distance(closest, _threatPosition) < AvoidDistance) { return(false); } } } else { return(false); } } } return(true); }