I have a script for enemy movement. The enemies can switch states between attacking, idle, flanking, etc.
During attacking the movement is perfect! However during my flanking state, the enemy slowly spins in a circle to the player’s flankPosition (behind the player). I have spent about half a day trying to debug, nothing makes sense! Any help is appreciated! I am putting my code below. For sake of easy reading, I have removed code that is not important!
BROKEN STATE (FLANKING)
Blockquote
void HandleFlankingState()
{
Vector2 flankingPosition = GetFlankingPosition();// Check if the monster has line of sight to the player bool hasLineOfSight = HasLineOfSight(); // Check if the monster has reached the flanking position if (Vector2.Distance(transform.position, flankingPosition) < nextWaypointDistance) { // Transition to attacking currentMonsterState = MonsterState.Attacking; } else { // Move towards the flanking position if (hasLineOfSight && seeker.IsDone()) { seeker.StartPath(transform.position, flankingPosition, OnPathComplete); } MoveAlongPath(); // Reuse the same movement logic as in MoveTowardsPlayer } } Vector2 GetFlankingPosition() { // Get the player's current movement direction Vector2 playerDirection = player.GetComponent<Rigidbody2D>().velocity.normalized; // If the player is not currently moving, use their facing direction if (playerDirection == Vector2.zero) { playerDirection = player.transform.right; // Assuming the player faces right by default } // Calculate a position behind the player Vector2 flankingPosition = (Vector2)player.transform.position - playerDirection * 2.0f; return flankingPosition; } void MoveAlongPath() { if (path == null || currentWaypoint >= path.vectorPath.Count) return; // Direction to the next waypoint Vector2 direction = ((Vector2)path.vectorPath[currentWaypoint] - (Vector2)transform.position).normalized; // Move the enemy enemyRigidbody.MovePosition(enemyRigidbody.position + direction * speed * Time.deltaTime); // Update the animation based on the direction monsterAnimator.SetFloat("XInput", direction.x); monsterAnimator.SetFloat("YInput", direction.y); ChangeAnimationState(MONSTER_WALK); // Check if close enough to the next waypoint and advance if (Vector2.Distance(transform.position, path.vectorPath[currentWaypoint]) < nextWaypointDistance) { currentWaypoint++; } }
WORKING STATE (ATTACKING)
void UpdatePath()
{// Skip path update if in Flanking state if (currentMonsterState == MonsterState.Flanking) return; // Check if the monster has line of sight to the player bool hasLineOfSight = HasLineOfSight(); // Only update the path if the monster has line of sight and the seeker is ready for a new path if (hasLineOfSight && seeker.IsDone()) { Path p = seeker.StartPath(transform.position, player.transform.position); p.BlockUntilCalculated(); // This will ensure the path is fully calculated if (!p.error) { // Extract the list of graph nodes from the path List<GraphNode> nodePath = p.path; // Check if a valid path is possible using the list of nodes if (PathUtilities.IsPathPossible(nodePath)) { path = p; currentWaypoint = 0; } } } }
void MoveTowardsPlayer()
{
if (path == null || currentWaypoint >= path.vectorPath.Count)
return;// Direction to the next waypoint Vector2 direction = ((Vector2)path.vectorPath[currentWaypoint] - (Vector2)transform.position).normalized; // Calculate and update lastDirection lastDirection = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg; // Move the enemy enemyRigidbody.MovePosition(enemyRigidbody.position + direction * speed * Time.deltaTime); // Update the animation based on the direction monsterAnimator.SetFloat("XInput", direction.x); monsterAnimator.SetFloat("YInput", direction.y); ChangeAnimationState(MONSTER_WALK); // Check if close enough to the next waypoint and advance if (Vector2.Distance(transform.position, path.vectorPath[currentWaypoint]) < nextWaypointDistance) { currentWaypoint++; } // Dampen the force over time forceToApply *= forceDamping; if (Mathf.Abs(forceToApply.x) <= 0.01f && Mathf.Abs(forceToApply.y) <= 0.01f) { forceToApply = Vector2.zero; } }