I have two coroutines that alternate when they run. When move_away()'s conditions are met, move_to() is disabled and the StartCoroutine function is called, and vice versa when move_to()'s conditions are met. This should cause the two to loop infinitely, but the ‘loop’ will run 3-10 times before one of them just fails to run at a StartCoroutine call.
I trimmed out everything not directly affecting the coroutines or the relevant variables. It is intended to have an object travel from the edge of the screen to the player, until other factors affect it.
Through testing, I’ve figured out that it always stops right after one of the StartCoroutine() functions are called.
public int is_move = 0; // -1 = move_away, 0 = not moving, 1 = move_to
public float walkSpeed = 0.1f;
private IEnumerator cor_away;
private IEnumerator cor_to;
private IEnumerator cor_circle;
private IEnumerator cor_lunge;
private Rigidbody2D body;
private GameObject player;
private Vector3 player_pos;
void Start () {
cor_away = move_away();
cor_to = move_to();
}
void FixedUpdate() {
player_pos = player.transform.position;
//Checks for moving out of bounds
if (tooFar () & is_move != 1) {
StopCoroutine (cor_away);
is_move = 1;
StartCoroutine (cor_to);
} else if (tooClose () & is_move != -1) {
StopCoroutine (cor_to);
is_move = -1;
StartCoroutine (cor_away);
}
}
IEnumerator move_to(){
while (is_move == 1) {
transform.position = Vector3.MoveTowards (transform.position, player_pos, walkSpeed);
if (tooClose()) {
is_move = 0;
}
yield return new WaitForSeconds(0.01f);
}
}
IEnumerator move_away(){
while (is_move == -1) {
transform.position = Vector3.MoveTowards (transform.position, player_pos, -walkSpeed);
if (tooFar()) {
is_move = 0;
}
yield return new WaitForSeconds(0.01f);
}
}
private Vector2 calc_dist(){
Vector3 diff = player_pos - transform.position;
float x = Mathf.Abs (diff.x);
float y = Mathf.Abs (diff.y);
return new Vector2 (x, y);
}
public bool tooFar () {
//Checks if the enemy is too close to the edge of the screen. Returns true if it is.
//Checks the position based on x and y coordinates
Vector2 dist = calc_dist();
float dX = dist.x;
float dY = dist.y;
if (dX > max_dist_h || dY > max_dist_v) {
return true;
} else {
return false;
}
}
public bool tooClose(){
//Checks if the enemy is too close to the player. Returns true if it is.
//Checks the position as a circle around the player (uses magnitude instead of coordinate distance)
float dist_mag = calc_dist ().magnitude;
if (dist_mag < min_dist) {
return true;
} else {
return false;
}
}
}