How can I prevent an object from exiting a circle? (2D)

I’m in 2D and I have an object inside the “Arena”, which has a circular shape. I want to prevent my object from exiting the Arena.

I have tried using a CircleCollider2D, but it works the other way around: my object can exit, but it can not get back in. I understand this is the intended behaviour, but is there a way to reverse this?

Is there another approach I should be using?

I would use distance joint as mentioned in the API:

First option: check out EdgeColliders 2D insted. They allow you to specify a set of line segments, and determine if they are touched. The line segments do not even need to enclose an area.

If the area is always a circle, that makes it very easy: Just check the objects distance from the center. This is a simply Vector3 subtraction operation. Subtract the position of the character from the vector3 that represents the center of the arena.
If the Magnitude of the resultant vector is LARGER that the radius you wish to allow, skip the code that normally moves the character. Or if using a rigidbody, set it’s velocity to zero (or to bounce back!) since it does it’s OWN movement.

I haven’t tested the idea–but in theory this should work. Rather than ‘stopping’ movement, you can limit the direction the controller is allowed to move by vector subtraction. Whatever direction your player is moving, it won’t be allowed to move in that specific direction if it leads the controller outside the arena boundary. I took the Debug comments out, because now you’ll need the angles and direction vector used to calculate the debug.ray in order to limit the direction of movement. Basically, you’re not interrupting player movement through a logic statement–you’re making a call to a function that blocks player movement in a certain direction if that direction of movement leads outside the arena boundary–otherwise, moving in another direction should be fine–like along the wall. It might need some tweaking–but this hypothetically should work–and you’re still looking at about 10 lines of code

Building on Glurths latter suggestion, this is a pretty sophisticated and simple way of handing it in C#–I also added a debugging code block so you can see the behavior. Make sure the game view has ‘gizmos’ turned on after you hit the play button or you want see the Debug ray lines. Take the Debugging code out and you should get your desired result with about 10 lines of code. It’s using trigonometry formulas to get the distance between 2 points in space:

//This assumes the center of the circular arena is 0,0,0 in worldspace
Vector3 arenaOriginPoint =;
//This is the radius of the arena
float arenaRadius = 20f;
Vector3 movement = new;
Update() {

//PUT YOUR NORMAL MOVEMENT CODE HERE--make sure to remove any other Move() commands

//call this function to adjust the player movement if the player hits the boundary
//it should only limit the players movement in a specific direction if that direction 
//goes outside the bounds
LimitPlayerMovementWithinArena(transform.position, arenaOriginPoint)

//now move the controller once the movement vectors have been processed


 LimitPlayerMovementWithinArena(Vector3 player, Vector3 arenaOrigin){

    	float tempAngle = Mathf.Atan((player.y - arenaOrigin.y) / (player.x - arenaOrigin.x));
    	Vector3 playerDirection = new Vector3(arenaRadius * Mathf.Cos (tempAngle), arenaRadius * Mathf.Sin (tempAngle),0);
    Debug.DrawRay (arenaOrigin, playerDirection,;
 //is the distance between the player and arena origin less than or equal to the arenas radius?
    	if( (Mathf.Sqrt(Mathf.Pow(player.x - enemy.x, 2) + Mathf.Pow(player.y - enemy.y, 2))  > = arenaRadius);
            movement -= playerDirection;

I don’t usually do this, but I was bored… Try this script I made. It takes the EdgeCollider, and with some basic calculus creates an array (List) of points that make up a circle. It then sets the points of the edge collider to the circle aray. Happy Coding!

using UnityEngine;
using System.Collections.Generic;
public class InverseCircleCollider : MonoBehaviour
    private float radius = 5;
    [SerializeField] [Range(8.0f, 100.0f)]
    private float circleQuality = 45;
    private List<Vector2> points = new List<Vector2>();
    private EdgeCollider2D edgeCollider;

	private void Awake ()
        edgeCollider = GetComponent<EdgeCollider2D>();

    private void OnDrawGizmosSelected()
          Gizmos.color =;
          Gizmos.DrawWireSphere(transform.position, radius);

    private void MakeCircle2D(float numVertices)
        float delta = (2 * Mathf.PI) / numVertices;
        for (int i = 0; i < numVertices; i++)
            float t = delta * i;
            float x = Mathf.Cos(t) * radius;
            float y = Mathf.Sin(t) * radius;
            points.Add(new Vector2(x, y));
        points.Add(new Vector2(points[0].x, points[0].y));
        edgeCollider.points = points.ToArray();