Skip to content

Instantly share code, notes, and snippets.

@penguin55
Created June 13, 2019 08:13
Show Gist options
  • Save penguin55/637f7b9635c07ea827faae28c2663584 to your computer and use it in GitHub Desktop.
Save penguin55/637f7b9635c07ea827faae28c2663584 to your computer and use it in GitHub Desktop.
Translate an Object inside a doughnut

How To Translate an Object Inside a 2D Doughnut with 2 Radius

This is my second post, you can read my post before : How To Translate an Object Inside a Circle with Radius

The explanation is same as before, but in here we are using 2 radius values, radiusIn and radiusOut.

This is the 2D doughnut

CircleDoughnut

distance = greenCircle position - centerCircle position

or you can count like this

distance = centerCircle position - greenCircle position

Same as when you restrict movement inside a circle. We use radius to define how far the object can move. So we can restrict the movement of object if the object moves out from the blue circle and holds the object to moves inside a red circle by its radius.

Restrict Move Inside Circle

Doughnut

Explanation

When the object distance to center is greater than radiusOut, then we make restrict move to the object so the object keeps inside in blue circle. When the object distance to center is smaller than radiusIn, then we make restrict move to the object so the object keeps outside in red circle. With this 2 conditions we can keeps the object still moving in blue area.

posObj is position of object according to center position of blue/red circle. The variable objPos absolutelly has same value with distance but objPos is the real value without absolut the value.

objPos = greenCirclePosition - centerCirclePosition

is not same with

objPos = centerCirclePosition - greenCirclePosition

After we count the objPos, then we will calculate the position of object when the object is going moves to outside blueCircle or going moves to inside redCircle.

Restrict for blueCircle objPos = objPos * radiusOut / distance

Restrict for redCircle objPos = objPos * radiusIn / distance

Formulas above will always results a position value that has a distance with a center less than equal to blue circle radius if the object going moves to outside blue circle and has a distance with a center more than equal to red circle radius if the object going moves to inside red circle.

After that, we must have exception to avoid Divide by zero, when we restrict move to inside red circle. When we restrict the movement inside a red circle, most likely the distance will have a value of zero when greenCirclePosition on the center of circle. So Dividing by zero will hapen when checking to restrict moves to inside red circle.

To avoid this we can generate any values to greenCircle position when its position at the center of circle.

Doughnut2

This is the result :

Doughnut

using UnityEngine;
public class Controller : MonoBehaviour
{
public Transform center;
public float radiusIn;
public float radiusOut;
void Update()
{
// Your code of movement
transform.position = TranslateInsideDoughnut(transform.position, center.position, radiusIn, radiusOut);
}
/// <summary>
/// This method do Translate around a circle doughnut between radiusIn with radiusOut.
/// Radius In must be lower than radius Out.
/// If it not, this method will don't work properly
/// </summary>
/// <param name="_position"> The position of object which will moving </param>
/// <param name="_center"> The center position of object to move </param>
/// <param name="_radiusIn"> radius inner circle </param>
/// <param name="_radiusOut"> radius outer circle </param>
/// <returns> Return a Vector2 inside of between radiusIn and radiusOut </returns>
public Vector2 TranslateInsideDoughnut(Vector2 _position, Vector2 _center, float _radiusIn, float _radiusOut)
{
if (_radiusIn >= _radiusOut)
{
Debug.LogError("Radius In is larger than Radius Out, this will makes this method don't work properly");
return _position;
}
float distance = Vector3.Distance(_position, _center);
if (distance != 0) {
if (distance <= _radiusIn) //To keep in the outside circle
{
Vector2 fromOriginToObject = _position - _center;
fromOriginToObject *= _radiusIn / distance;
return _center + fromOriginToObject;
}
}
else //When the _position is the same point with circle position. The distance will be 0
{
return new Vector2(Random.Range(-_radiusIn/2,_radiusIn/2) , Random.Range(-_radiusIn/2,_radiusIn/2));
}
if (distance >= _radiusOut) //To keep in the inside circle
{
Vector2 fromOriginToObject = _position - _center;
fromOriginToObject *= _radiusOut / distance;
return _center + fromOriginToObject;
}
return _position;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment