- Home /
Calculate vector exactly between 2 vectors
Lets say i have vector.forward and vector.right. How would i use those two vectors to get the vector pointing forwardright? The reason im asking is because im implementing motion relative to camera. I was able to successfully implement left and right addforce directions using
cameraRelativeRight = cam.TransformDirection (Vector3.right);
and up,down using
cameraRelativeUp = cam.TransformDirection (Vector3.forward);
cameraRelativeUp.y = 0;
cameraRelativeUp = cameraRelativeUp.normalized;
but using the same approach for upright didnt work
cameraRelativeUpRight = cam.TransformDirection (Vector3(1,0,1));
cameraRelativeUpRight.y = 0;
cameraRelativeUpRight = cameraRelativeUpRight.normalized;
The resulting vector is skewed more to the right, and i assume that's because i modified the y component of the forward vector which lessened its magnitude in that direction.
I was thinking then to somehow combine the cameraRelativeUp and cameraRelativeRight vectors since individually they are correct, but i'm a bit confused as to how to do this? help please :)
Answer by whydoidoit · Apr 12, 2013 at 09:11 PM
The Vector half way between two normalized vectors is their sum, normalized.
var halfWayVector = (Vector3.up + Vector3.right).normalized;
Thanks. Do you have an intuitive explanation for why exactly this works? Having some trouble wrapping my head around it.
Answer by Dracorat · Apr 12, 2013 at 09:10 PM
If you want the weights of the original Vector3 to count toward the final weight, it's:
Vector3 first = //Something
Vector3 second = //Something else
Vector3 bisection = (first + second) * 0.5;
If you want it normalized, you have to normalize the first and second vectors first, then normalize the third. (This will find the vector that bisects the angle rather than bisects by weight.)
And btw, bisection is the mathematical term for what you're asking for.
The reason i normalize the forward vector is because i dont want a y component, to prevent any vertical motion, but by removing it the total magnitude is less then 1, which is why i normalized.
Im going to try your suggestion with my cameraRelativeUp and CameraRelativeRight.
ok great the direction is exactly the bisection of the two vectors but now i have the problem of weight or force.
For Right and Up i simply did
rigidbody.AddForce(fs * cameraRelativeUp);
rigidbody.AddForce(fs * cameraRelativeRight);
with fs being the force that will allow the object to travel at the maximum velocity i require.
This following code does not work right however
rigidbody.AddForce(fs * cameraRelativeUpRight);
I assume this is because the fs is split between up and right but I'm having trouble figuring out how to calculate the proper fs to give the same net force diagonally with the same maximum velocity as the simpler straight Up and Right directions.
The only solution i can think of that would probably work is to simply use a^2 + b^2 = c^2 to find the separate Up and Right forces relative to fs, and then apply them as 2 separate forces on the rigidbody and the net force would be fs in the diagonal UpRight direction.
I'm just hoping its possible to find and apply one force with cameraRelativeUpRight ins$$anonymous$$d for simplicity.
@luniac - adding two vectors together creates a vector between the two:
If the two vectors are unit vectors (length of 1 like .up or .right) then the result is a vector exactly between them but with a length > 1. You just normalize it (like I posted in my answer below - which does exactly what you want).
The summation vector is still the same vector (but now it isn't unit length, so a bunch of techniques won't work on it any more, but it's fine as a direction).
$$anonymous$$ultiplying it by 0.5 doesn't work because that isn't the length of a line, you need the square root of the sum of the two sides - so actually the length of the vector: Vector3.up + Vector3.right is sqrt(2) = 1.414 - hence you just normalized it so you can use it more easily - this just turns it back into a unit vector by doing the square root.
@luniac I might suggest, use Debug.DrawLine very frequently. I use it constantly. Really you will solve all problems, by experimenting for some time and actually drawing out your vectors in some way. (the gizmos system is also very useful for this). It's a bit like using wolfram, mathematica or whatever to visualise stuff while you are figuring it out.
Hope it helps
Answer by dexter_andre · Dec 02, 2017 at 03:28 PM
TL;DR:
Two unit vectors: (a + b) / 2, and then normalize it.
Two non-unit vectors with same magnitude: (a + b) / 2, then normalize it, and then multiply by a's magnitude (b's magnitude will also work, as they are the same).
Two vectors with different magnitude: Vector3.Slerp(a, b, 0.5).
Define half-way vector:
First of all, we have to define what exactly we mean by a vector that is half-way between two vectors. Is it:
A vector that literally points to a position between the two original vectors, or
A vector that points in the direction half-way from the first to the second?
The second option is most useful when if comes to interpreting vectors as directions, rather than points, which often happens to be the case with camera programming. Also, we have to consider whether the vectors involved are unit (i.e. their magnitude == 1), and if they have the same magnitude or not.
For normalized vectors:
(This will work exactly the same in 3D.)
Firstly, we create the two vectors we want to find the half-way vector of. In the image, I call them a and b.
Then we add a and b to get a new vector called c. This is a vector in the direction half-way between a and b, but its magnitude is sqrt(2).
If we want a vector that is linearly half-way between a and b, then all we have to do is to divide c by 2. This returns a vector half-way between a and b, but its magnitude is 0.5.
However, if we want a vector that is rotated half-way between a and b, then we can normalize c. This normalized vector is half-way between a and b, and it has the same magnitude.
Note that you could choose to normalize either [1, 1] or [0.5, 0.5], and you would still get the same vector, but normalizing [1, 1] in this case would save some computation.
// a and b are unit vectors (magnitude == 1).
Vector3 a = new Vector3(1, 0, 0);
Vector3 b = new Vector3(0, 1, 0);
// Position half-way beteen a and b:
Vector3 cL = (a + b) / 2.0f;
// Rotated half-way between a and b:
Vector3 cR = (a + b).normalized;
This yields cL = [0.5, 0.5, 0], and cR = [0.71, 0.71, 0].
For non-unit vectors with same magnitude:
If your two vectors are not unit (i.e. they do not have magnitude == 1), but still have the same magitude, then you could do the same as above, but after having normalized c you then scale it up by either a's or b's magnitude.
// Neither a and b are unit, but
// they have the same magnitude.
Vector3 a = new Vector3(3, 0, 0);
Vector3 b = new Vector3(0, 3, 0);
// Position half-way between a and b:
// (This is the same as above)
Vector3 cL = (a + b) / 2.0f;
// Rotated half-way between a and b:
// (Normalize it first, then scale it by
// a's magnitude (either a or b would work here).
Vector3 cR = (a + b).normalized * a.magnitude;
This yields cL = [1.5, 1.5, 0], and cR = [2.12, 2.12, 0].
For vectors with different magnitude:
Slerp. Slerp stands for "spherical linear interpolation", and it interpolates along a spherical shape, rather than just a line, which is what Lerp does.
// a and b do not have the same magnitude.
Vector3 a = new Vector3(1, 0, 0);
Vector3 b = new Vector3(0, 3, 0);
// Position half-way between a and b:
// (This is the same as above)
Vector3 cL = (a + b) / 2.0f;
// Rotated half-way between a and b:
Vector3 cR = Vector3.Slerp(a, b, 0.5f);
This yields cL = [0.5, 1.5, 0], and cR = [1.41, 1.41, 0]. Note that the x-component of cR actually extends the original x-value. This is because Vector3.Slerp creates an artificial sphere somewhere so that both vectors touch the crust of the sphere. Because they do not share the same magnitude, the sphere's center has to be moved away, and this in turn creates this extra curvature.
Also related:
I've created a quick C# script that we can use to play around with Lerp, Slerp, and Nlerp. Put this script onto any GameObject, and create a UI Slider to use as input.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class InterpolationTest : MonoBehaviour
{
// Slap this script onto any GameObject, and set a Slider to see
// the effects of Lerp, Slerp, and Nlerp on vectors.
// Try to experiment with non-unit vectors (i.e. vectors whose
// magnitude is not == 1). Try to spot the difference and similarities
// in the angles between the Slerp and Nlerp functions.
// Set the posA, posB, and posC to something like [0, 0, 0], [3, 0, 0], and [6, 0, 0]
[Header("Parameters")]
public Slider slider;
public float t;
public Vector3 a;
public Vector3 b;
[Header("Positioning")]
public Vector3 posA;
public Vector3 posB;
public Vector3 posC;
[Header("Colors")]
public Color colA;
public Color colB;
public Color colC;
[Header("Results")]
[SerializeField]
private Vector3 resultLerp;
[SerializeField]
private float angleLerp;
[SerializeField]
private Vector3 resultSlerp;
[SerializeField]
private float angleSlerp;
[SerializeField]
private Vector3 resultNlerp;
[SerializeField]
private float angleNlerp;
private void Update ()
{
// Updating slider
t = slider.value;
float max = a.magnitude > b.magnitude ? a.magnitude : b.magnitude;
// Lerp
Debug.DrawLine(posA, a + posA, colA);
Debug.DrawLine(posA, b + posA, colB);
resultLerp = Vector3.Lerp(a, b, t);
Debug.DrawLine(posA, resultLerp + posA, colC);
angleLerp = Vector3.Angle(a, resultLerp);
// Slerp
Debug.DrawLine(posB, a + posB, colA);
Debug.DrawLine(posB, b + posB, colB);
resultSlerp = Vector3.Slerp(a, b, t);
Debug.DrawLine(posB, resultSlerp + posB, colC);
angleSlerp = Vector3.Angle(a, resultSlerp);
// Nlerp
Debug.DrawLine(posC, a + posC, colA);
Debug.DrawLine(posC, b + posC, colB);
resultNlerp = resultLerp.normalized;
Debug.DrawLine(posC, resultNlerp + posC, colC);
angleNlerp = Vector3.Angle(a, resultNlerp);
}
}
Answer by RyanZimmerman87 · Apr 12, 2013 at 09:07 PM
To be honest I've never used TransformDirection so I could be way off here. I'll throw a few examples in case they might work:
enter code here:
//rotation with angles instead of vectors:
transform.RotateAround (transform.position, transform.up, 90f);
transform.RotateAround (transform.position, transform.right, 90f);
//rotation with making camera look at vectors:
// you may need to add all these vectors below to your original camera transform position depending on how you are coding all this.
Vector3 vectorUpPosition = new Vector3 (0, 1, 0);
Vector3 vectorRightPostition = new Vector3 (1, 0, 0);
vector3 cameraLookVectorPosition = vectorUpPosition + vectorRightPosition;
transform.LookAt (cameraLookVectorPosition);
//this.transform can be very helpful for looking at objects to depending on what you're doing. you could set a vector like:
playerDestinationVector = new Vector3 (rayHitObject.transform.position.x, this.transform.position.y, rayHitObject.transform.position.z);
this.transform.LookAt (playerDestinationVector)
//in above example the transform will only rotate the x and z coordinates. The Y will remain where it currently is due to the this.transform statement.
There's a few quick ideas it would be easier to give you an answer if you explained how you want the camera to function, I assume it doesn't just look randomly in certain directions like your example suggests?
Your answer
Follow this Question
Related Questions
Movement relative to Camera and XZ Plane 1 Answer
Camera Relative Movement With Rigidbody.AddForce 2 Answers
Move player relative to camera 0 Answers
Relative Movement Problem 1 Answer
How to smooth my camera (Vector3.Lerp) 0 Answers