Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by luniac · Apr 12, 2013 at 08:49 PM · cameramovementvector3relative

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 :)

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

4 Replies

· Add your reply
  • Sort: 
avatar image
11
Best Answer

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;
Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image ahung89 · Nov 17, 2017 at 11:49 PM 0
Share

Thanks. Do you have an intuitive explanation for why exactly this works? Having some trouble wrapping my head around it.

avatar image
7

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.

Comment
Add comment · Show 11 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image luniac · Apr 12, 2013 at 09:19 PM 0
Share

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.

avatar image luniac · Apr 13, 2013 at 03:40 AM 0
Share

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.

avatar image luniac · Apr 13, 2013 at 03:46 AM 0
Share

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.

avatar image whydoidoit · Apr 13, 2013 at 07:14 AM 1
Share

@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.

avatar image Fattie · Apr 13, 2013 at 09:25 AM 2
Share

@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

Show more comments
avatar image
1

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:

  1. A vector that literally points to a position between the two original vectors, or

  2. 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:

See image

(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);
     }
 }

skjermbilde.png (89.3 kB)
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
0

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?

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

15 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

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


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges