Trigonometry: finding the vector3 positon of one corner using one side and one angle.

Hello, I’ve been stuck with this problem for days and it’s really killing me.

I have a perspective camera rotated 90 degrees on the x-axis that is positioned 20 units up along the y-axis.

When I click somewhere on the screen I want to instantiate an object in that direction, and I want this objects position to be 0 on the y-axis. This does not work however.

This is the code I have so far.

	void Update () {

		if(Input.GetMouseButton(0)) {
			ray = Camera.main.ScreenPointToRay(Input.mousePosition);

			angle = Vector3.Angle(Vector3.down, ray.direction);
			hypotenuse = ray.origin.y / Mathf.Cos(angle);
			pos = ray.origin + ray.direction * hypotenuse;

			Instantiate(debug, pos, Quaternion.identity);

		}
    }

When I do this, sometimes the generated position ends up in the opposite direction and it doesn’t under any circumstances have the y-axis value of 0.

Am I not using SOHCAHTOA right?

I could just have a huge, flat collider with transform.position.y = 0 and instantiate objects on the hit.point of the ray, but I don’t want to do this because it’s ugly and I won’t learn anything if I keep running from my problems.

Any help at all would be appreciated.

Your problem is that Vector3.Angle returns an angle in degrees while Mathf.Cos expects an angle in radians like in most programming languages. You can use Mathf.Deg2Rad to convert it from degree to radians, just multiply the angle with this constant (which is PI/180 or (2*PI/360))

if(Input.GetMouseButton(0))
{
    ray = Camera.main.ScreenPointToRay(Input.mousePosition);
    angle = Vector3.Angle(Vector3.down, ray.direction) * Mathf.Deg2Rad;
    hypotenuse = ray.origin.y / Mathf.Cos(angle);
    pos = ray.GetPoint(hypotenuse);
    
    Instantiate(debug, pos, Quaternion.identity);
}

However, as alternative you could use the Plane class like this:

void Update ()
{
    if(Input.GetMouseButton(0))
    {
        ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        Plane groundPlane = new Plane(Vector3.up,Vector3.zero);
        float dist;
        if (groundPlane.Raycast(ray, out dist))
        {
            pos = ray.GetPoint(dist);
            Instantiate(debug, pos, Quaternion.identity);
        }
    }
}

Since the mathematical plane doesn’t change you can create it once in Awake and store it in a member variable.