Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unity - Get point on edge of the screen that object directed to?

So this is my problem:

I have an object within the screen that points to a specific direction. For demonstration purposes, I've added a LineRenderer to show this direction.

enter image description here

My final goal is to find the distance between object and the world point where this purple ray intersects with the border of the screen (white outline).

float DistToScreenEdge = Vector2.Distance(Object.transform.position, PointOnScreenEdge);

But for that I need to get this point, and I have no clue how to do that.

Vector2 PointOnScreenEdge = ???

PNG-example

So, the Question: How can I get that "PointOnScreenEdge"?

Note that I always know the direction which object facing and its world coordinates.

On the Internet, I read that to find a world point relative to the screen, you can use Camera.ScreenToWorldPoint() and Camera.ViewportToWorldPoint() but I could not figure out how to use them correctly in this situation.

Thank you for the help.

like image 542
sweatyDev Avatar asked Sep 01 '25 05:09

sweatyDev


1 Answers

There is GeometryUtility.CalculateFrustumPlanes which returns an array of the six planes making up the Camera frustrum.

Ordering: [0] = Left, [1] = Right, [2] = Down, [3] = Up, [4] = Near, [5] = Far

You are interested in the ones 0 to 3 and could then do a Plane.Raycast against them like

[SerializeField] private Camera mainCamera;

private readonly Plane[] planes = new Plane [6];

void Update()
{
    // Wherever you get these to from
    Vector3 origin;
    Vector3 direction;

    var ray = new Ray(origin, direction);

    var currentMinDistance = float.Max;
    var hitPoint = Vector3.zero;
    GeometryUtility.CalculateFrustumPlanes(mainCamera, planes);
    for(var i = 0; i < 4; i++)
    {
        // Raycast against the plane
        if(planes[i].Raycast(ray, out var distance))
        {
            // Since a plane is mathematical infinite
            // what you would want is the one that hits with the shortest ray distance
            if(distance < currentMinDistance)
            {
                hitPoint = ray.GetPoint(distance);
                currentMinDistance = distance;
            } 
        }
    }  

    // Now the hitPoint should contain the point where your ray hits the screen frustrum/"border"
    lineRenderer.SetPosition(1, hitPoint);
}

Depends a bit on if your camera is actually moving/rotating/scaling you might want to get the frustrum planes only once at the beginning.

You should also cache the Camera.main reference once at the beginning.

like image 57
derHugo Avatar answered Sep 02 '25 18:09

derHugo