Rotate an object 180 degrees smoothly in a particular direction

My current code achieves the result I want but is horribly inefficient and bug prone. I’m hoping someone can explain to me how to get an object to smoothly flip in a particular direction depending on the current direction value.

public void OnTriggerExit () {

	if (!isRunning){
		//get the direction to flip in
		currentPlayer = FindCurrentPlayer ().GetComponent<PlayerControl> ();
		flipDirection = currentPlayer.direction;
        //start flip coroutine
        isRunning = true;
        StartCoroutine(Flip());
	}
}

// Flip Tile
IEnumerator Flip(){

	if (flipDirection == "up")
	{
		transform.Rotate(flipSpeed,0,0, Space.World);
		while (Flipping())
		{
			transform.Rotate(flipSpeed,0,0, Space.World);
			yield return null;
		}
	}
	if (flipDirection == "left")
	{
		transform.Rotate(0,0,flipSpeed, Space.World);
		while (Flipping())
		{
			transform.Rotate(0,0,flipSpeed, Space.World);
			yield return null;
		}
	}
	if (flipDirection == "down")
	{
		transform.Rotate(-flipSpeed,0,0, Space.World);
		while (Flipping())
		{
			transform.Rotate(-flipSpeed,0,0, Space.World);
			yield return null;
		}
	}
	if (flipDirection == "right")
	{
        transform.Rotate(0,0,-flipSpeed, Space.World);
		while (Flipping())
		{
			transform.Rotate(0,0,-flipSpeed, Space.World);
			yield return null;
		}
	}
}

//Check if tile is still flipping (hasn't reached a point where it can stop yet)
bool Flipping() {

	if (transform.rotation.x != 1 && transform.rotation.x != -1 && transform.rotation.y != 1 && transform.rotation.y != -1 && transform.rotation.z != 1 && transform.rotation.z != -1 && transform.rotation.w != 1 && transform.rotation.w != -1)
    {
        return true;
	}
	else{
		isRunning = false;
        occupied = false;
		return false;
	}
}

The code isn’t that bad, but it can be greatly simplified by creating helper variables, for example for the rotation. A different problem is that the code rotates independently from the frame rate, so it can look jerky. It is better to specify the duration of the flipping, and use Quaternion.Lerp() or Slerp() to rotate (see usage below).

Also note that in this form the OnTriggerExit() won’t be called when exiting a trigger, because it doesn’t match the the Unity callback function’s signature, which has a Collider parameter.

Finally, it would be a lot more efficient to define an enum for the flipDirection instead of using a string.

Now some code:

public enum FlipDirection { UP, DOWN, LEFT, RIGHT }; // change type of flipDirection in PlayerControl to FlipDirection

private Coroutine flipCoroutine;

public void OnTriggerExit (Collider other) {
    if (flipCoroutine != null) { return; }
    PlayerControl playerControl = other.GetComponent<PlayerControl>();
    if (playerControl != null) { flipCoroutine = StartCoroutine(Flip(playerControl.direction); }
}

private IEnumerator Flip (FlipDirection flipDirection) {
    Quaternion startRotation = transform.rotation;
    Quaternion targetRotation;    
    switch (flipDirection) {
        case FlipDirection.UP: targetRotation = Quaternion.Euler(90, 0, 0); break;
        case FlipDirection.DOWN: targetRotation = Quaternion.Euler(-90, 0, 0); break;
        case FlipDirection.LEFT: targetRotation = Quaternion.Euler(0, 0, 90); break;
        case FlipDirection.RIGHT: targetRotation = Quaternion.Euler(0, 0, -90); break;
        default: flipCoroutine = null; yield break; // unexpected case, stop coroutine
    }

    float t = 0;
    while (t < flipDuration) {
        t += Time.deltaTime;
        transform.rotation = Quaternion.Slerp(startRotation, targetRotation, t / flipDuration);
        yield return null;
    }
    transform.rotation = Quaternion.Slerp(startRotation, targetRotation, 1); // make sure the flipping completes precisely
    flipCoroutine = null; // mark the flipping finished
}

Note, that the above code arrives from any starting rotation to the target rotation over the same time. If the object does not start out in an exactly opposite direction, it will rotate slower. However, I don’t know of an equivalent of InverseLerp() for rotations so you might need to find a solution for this if this is a problem.