Here is a bit of math. If you have 3 points, say A, B and C - then first make a line L1 that passes between A and B. Next, make another line that passes between B and C. You end up with equations:
Next, get the perpendicular lines which should pass through the mid-points of the lines AB and BC. Then the centre of the circle will just be the intersection of these 2 perpendicular lines.
I quickly put the following script together to demonstrate how you would go about doing this. It’s commented, talking about how each part works. To see this in action, you’ll need three objects; 2 cubes and a sphere. Attach this script to the sphere, and set the 2 cubes as the start and end points of your arc (keep in mind this particular one is a hybrid 2D/3D solution on the XZ axis, so you’ll want to look at it top-down). Use the ‘position’ variable to move the sphere along the arc.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ArcTest : MonoBehaviour
{
public Transform startPoint; //Arc start object
public Transform endPoint; //Arc end object
public float arcHeight = 2f; //Max height of the arc
[Range(0f,1f)]
public float position = 0f; //How far along the arc the object should be
//This basically returns the 2D centre of the circle in the [x,y] of the Vector3 and the radius in the [z] of the Vector3
//Adapted from Erk Ekin's answer to https://math.stackexchange.com/questions/827072/finding-an-equation-of-circle-which-passes-through-three-points
Vector3? Circle3 (Vector2 p0, Vector2 p1, Vector2 p2)
{
if (p1.x == p0.x || p2.x == p1.x)
return null;
float mr = (p1.y - p0.y) / (p1.x - p0.x);
float mt = (p2.y - p1.y) / (p2.x - p1.x);
if (mr == mt)
return null;
float x = (mr * mt * (p2.y - p0.y) + mr * (p1.x + p2.x) - mt * (p0.x + p1.x)) / (2f * (mr - mt));
float y = (p0.y + p1.y) / 2f - (x - (p0.x + p1.x) / 2f) / mr;
float radius = Mathf.Sqrt (Mathf.Pow (p1.x - x, 2f) + Mathf.Pow (p1.y - y, 2f));
Vector2 centre = new Vector2 (x, y);
return new Vector3 (centre.x, centre.y, radius);
}
public void Update ()
{
//For the arc beginning and end points, I used the [x,z] axis in 3D and looked down (for testing)
Vector2 a = new Vector2 (startPoint.position.x, startPoint.position.z);
Vector2 b = new Vector2 (endPoint.position.x, endPoint.position.z);
//This finds the relative 'up' direction from the two given start and end points
Vector3 dir3 = Vector3.Cross ((endPoint.position - startPoint.position).normalized, Vector3.down).normalized;
Vector2 dir = new Vector2 (dir3.x, dir3.z);
//This is the actual height of the arc. We want the minor arc, so clamp it such that it can't be more than the radius of the circle
float height = Mathf.Min (arcHeight, Vector3.Distance (startPoint.position, endPoint.position) * 0.5f);
//This is the middle point (you can replace it with your own, I just calculate it automatically based on the two input points)
Vector2 c = (a + b) * 0.5f + dir * height;
//Find the actual centre and radius of the circle
//This is a nullable type because there's some funky maths, so we need to make sure we actually get useable values
Vector3? circle = Circle3 (a, c, b);
if (circle == null)
return;
//Extract the values from the nullable type
Vector2 centre = circle.Value;
float radius = circle.Value.z;
//Find the relative angles to the 'origin' and blend between them so that;
// position(0) = the start of the arc
// position(1) = the end of the arc
//Also make sure we're in radians
float t = Mathf.Lerp (Vector2.SignedAngle (Vector2.right, a - centre), Vector2.SignedAngle (Vector2.right, b - centre), position) * Mathf.Deg2Rad;
//Find the current point on the arc through sin/cos circle function using calculated radius and centre
Vector2 pos = centre + new Vector2 (Mathf.Cos (t), Mathf.Sin (t)) * radius;
//Move this object to the target point on the arc
transform.position = new Vector3 (pos.x, 0, pos.y);
}
}
For some reason I can not find the question at the moment but there was exact the same question already asked here. I’ve written this method and actually created this gif image: