# How can I set up a 2D circular boundary in Unity?

I wanted to create a virtual analogue stick on Unity.

I figured a very simple, 2 part method setting up a tether to the middle of a doughnut-container and a boundary would work. While the tether was quickly solved just by using Vector2.MoveTowards, the boundaries would be much harder to solve.

I initially tried to create a 2D circle collider around the doughnut-container but I didn't know how to reverse its collisions to keep the cursor inside. Later, I tried to set up a square shaped boundary by setting up the limits of the x and y coordinates the cursor cannot exceed (these limits were also made according to the doughnut-container). Thus was done with multiple if statements:

 if (currentPoint.y >= 2.7f){currentPoint.y = 2.7f;}
if (currentPoint.x >= 2.5f){currentPoint.x = 2.5f;}
if (currentPoint.y <= -2.7f){currentPoint.y = -2.7f;}
if (currentPoint.x <= -2.5f){currentPoint.x = -2.5f;}


However, when testing the code out, the cursor still exceeded the boundaries given:

Minimum reproducible code for the cursor:

public class menuScript : MonoBehaviour
{
public float speed;
public Vector2 originPoint;
private Vector2 currentPoint;
// Start is called before the first frame update
void Start()
{
Vector2 originPoint = transform.position;
}

// Update is called once per frame
void Update()
{
currentPoint = transform.position;
float step = 50 * Time.deltaTime;
float vertical = Input.GetAxis("Vertical") * Time.deltaTime * speed;
float horizontal = Input.GetAxis("Horizontal") * Time.deltaTime * speed;

if (horizontal != 0 || vertical != 0)
{
transform.Translate(horizontal, vertical, 0);
if (currentPoint.y >= 2.7f){currentPoint.y = 2.7f;}
if (currentPoint.x >= 2.5f){currentPoint.x = 2.5f;}
if (currentPoint.y <= -2.7f){currentPoint.y = -2.7f;}
if (currentPoint.x <= -2.5f){currentPoint.x = -2.5f;}
}
else
{
transform.position = Vector2.MoveTowards(transform.position, originPoint, step);
}
}
}


Your if-else block for constraining the position of the stick looks like this:

if (currentPoint.y >= 2.7f){currentPoint.y = 2.7f;}
if (currentPoint.x >= 2.5f){currentPoint.x = 2.5f;}
if (currentPoint.y <= -2.7f){currentPoint.y = -2.7f;}
if (currentPoint.x <= -2.5f){currentPoint.x = -2.5f;}


This is going to lock the stick in a square region, not a circular region as you probably intend. There are several ways to enforce a region that is actually circular. Here's a simple one:

float radius = 2.5f;
float distance = Vector3.Distance(transform.position, originPoint);
float excess = distance - radius;
if (excess > 0) transform.position = Vector2.MoveTowards(transform.position, originPoint, excess);


This checks if the distance to the center is further than the maximum radius, and if so moves back towards the center the exact distance that is needed to put it on the edge of the circle. For example, if the radius is 2.5 but the measured distance is 3.7, it will move the stick 1.2 units back towards the center.

It's also worth noting there are numerous virtual joystick packages on the Unity Asset Store, and there is one included in Unity Standard Assets.

EDIT: As noted by DMGregory, you can also do this:

float radius = 2.5f;
Vector2 offset = transform.position - originPoint;

float radius = 2.5f;

• You can use Vector2.ClampMagnitude for this instead for a slightly more concise solution. Jul 8, 2020 at 11:15