How to transform/rotate a vector onto the same plane as another vector

I have 2 vectors, a predetermined vector and a vector with random x and z values. The random vector starts with a y value of 0, but I need to set it to a value that is in the same plane as the predetermined vector.

For example, I have the predetermined vector (3, 1, 2) and a vector with values (2,0-2). How can I make sure the effect in the below image is achieved? These are non-normalized vectors, in my game the vectors are normalized.

Part 1

The problem needs a bit more specification - “in the same plane as the predetermined vector” doesn’t define a unique plane. For instance, the x=3 plane passes through it, as do the y=1 and z=2 planes. Generally, you need three points to define a plane, or a normal to the plane and one point (usually, a point on that normal vector), or some other definition with enough constraints in it.

Taking the diagram as indicative, though, what it /looks/ like is that the plane shown is defined as including also the y-axis (assuming y-axis is marked green, as in Unity). In which case, it’s the plane 2x=3z, which can also be defined as having the normal vector [2, 0, -3] (errr… I think…) and passing through the origin. We could define the plane shown with these two data:

Normal vector N = [2, 0, -3]
Point in plane P = [0, 0, 0]

Doesn’t matter if that’s actually your plane, the point is you need it in some standard form.

Part 2

The problem needs a bit more specification, though, again - “in the same plane as the predetermined vector” doesn’t define a unique point in a given plane. The diagram seems to be showing projection along the blue axis (z?), but the vector (2, ?, -2) suggests it’s a projection in y. So you’ll need to specify more about the result than just it being in the plane.

A common extra bit of information is to say ‘the nearest point on the plane’, so I’ll go with that, but a projection along any axis, or indeed any direction, is also a thing you might want to do. The procedure for those is a bit different, but the tools are from the same toolbox.

Part 3

Assuming you have a normal vector, N, and any point in the plane P, you can project your ‘random vector’ X onto the nearest point on that plane by doing:

X += Vector3.Project(P, N) - Vector3.Project(X, N)

noting that you can precompute the first term since it’s the same for any X.

The fact that this is so neat underlines why people like to represent planes in N/P format.

Forgive any silly mistakes, I’m not testing this.

link text

using UnityEngine;
public class AdventuresInVectorProjections : MonoBehaviour
{
    [SerializeField] Vector3 _tangent = Vector3.one;// this is your "predetermined vector"
    [SerializeField] Vector3 _approxNormal = Vector3.up;// an additional normal to help define a plane
    void OnDrawGizmos ()
    {
        Vector3 betterNormal = Vector3.Cross( _tangent.normalized , -Vector3.Cross(_tangent.normalized,_approxNormal) );
        Vector3 X0Z = Quaternion.Euler(0,((System.DateTime.Now.Millisecond % 1000)/1000f)*360f,0) * Vector3.right;
        
        // option 1, point above X0Z that lies on a plane:
        new Plane{ normal=betterNormal }.Raycast( new Ray{ origin=X0Z , direction=Vector3.up } , out float Y );
        Vector3 XYZ = new Vector3( X0Z.x , Y , X0Z.z );

        // option 2, nearest point on a plane:
        // Vector3 XYZ = Vector3.ProjectOnPlane( vector:X0Z , planeNormal:betterNormal );

        Vector3 pos = transform.position;
        Gizmos.color = Color.magenta; Gizmos.DrawLine( pos , pos + _tangent );
        Gizmos.color = Color.cyan * 0.5f; Gizmos.DrawLine( pos , pos + _approxNormal );
        Gizmos.color = Color.cyan; Gizmos.DrawLine( pos , pos + betterNormal );
        Gizmos.color = Color.green * 0.5f; Gizmos.DrawLine( pos , pos + X0Z );
        Gizmos.color = Color.green; Gizmos.DrawLine( pos , pos + XYZ );
        Gizmos.matrix = Matrix4x4.Rotate( Quaternion.LookRotation(_tangent,betterNormal) );
        Gizmos.color = new Color( 0.1f , 1f , 0.1f , 0.1f );
        Gizmos.DrawCube( pos , new Vector3{x=3,z=3} );
    }
}