- Home /

# [MATH] Vectors, magnitudes, and bears; Oh My! -Solved

# Project

Im doing a little space ship project that is a 2.5D game and the space ship stays on the flat plane. IE: it only travels in the X and Z axis.

**And I am looking to find a Mathematical Function** for this problem:

# Part 1:

Okay, so now that you know that. When the player chooses to orbit around a planet or sun, this particular code will run. As you can see; it simply clears a couple of variables and it creates an imaginary circle, a radius that I will use to help with the ship's orbitting distance. Obviously I would orbit a small ship alot closer than if the object I was orbitting was a SUN or PLANET.

```
if (systemStatus == 2) // [ -----------------------[ORBIT]----------------------------------------------------------------------
{
tempDirection = new Vector3(0f,0f,0f);
distanceToTarget = 0f;
//we need to RETURN the orbiting targetDirection <-- A Vector3
// IF TAG = "ENVIRONMENT", = SPHERE COLLIDER
// IF TAG = PLAYER OR ENEMY OR DRONE = MESH COLLIDER
if (myTarget.tag == ("Environment"))
{
myTargetsRadius = myTarget.GetComponent <SphereCollider> ().radius;
}
```

# Part 2:

Now we calculate the distance ( in float ) between the ship & that radius we just obtained.

```
////////////// NOW WE CALCULATE THE DISTANCE ///////////////////////
//xd = x2-x1
//yd = y2-y1
//zd = z2-z1
//Distance = SquareRoot(xd*xd + yd*yd + zd*zd)
float calcX = (this.transform.position.x - myTarget.transform.position.x) - myTargetsRadius;
float calcY = (this.transform.position.y - myTarget.transform.position.y) - myTargetsRadius;
float calcZ = (this.transform.position.z - myTarget.transform.position.z) - myTargetsRadius;
distanceToTarget = Mathf.Sqrt (calcX*calcX + calcY*calcY + calcZ*calcZ);
```

# Part 3:

If we are not our underneath our optimal range, then we need to increase our distance until we go to it. However, if we are above our optimal range, then we need to decrease our distance.

```
if (distanceToTarget < optimalRange)
{
//tempDirection = AwayFromTarget
tempDirection = this.transform.position - myTarget.transform.position;
}
if (distanceToTarget > optimalRange)
{
//tempdirection = TowardsTarget
tempDirection = myTarget.transform.position - this.transform.position;
}
```

**Then:** Add this Vector to our tangentVector which is a vector perpendicular to the the radius of a point in space... of our (planet,sun,whatever)

```
if (orbitDirection == 1) //clockwise
{
// *** WARNING *** Unity uses the LEFT HAND RULE: http://docs.unity3d.com/ScriptReference/Vector3.Cross.html
Vector3 a = myTarget.transform.position - this.transform.position;
Vector3 b = this.transform.up;
Vector3 c = Vector3.Cross (a,b);
float tempStrength;
float cStrength;
tempStrength = Mathf.Abs (optimalRange - distanceToTarget);
float ratio = 100/ (optimalRange - lowerEndRange); // so here is how we got that ratio multiplyer number... By basically putting it in an aspect in terms of percentage. /100
tempStrength = tempStrength * ratio; // .4166 ONLY if the upper end is 20% of 400 and lower end is 20% of 400, how did we get this number though...Explained one line up..
cStrength = 100 - tempStrength;
tempDirection = tempDirection.normalized;
tempDirection = tempDirection * tempStrength;
c = c.normalized;
c = c * cStrength;
tempDirection = tempDirection + c;
}
```

# THE PROBLEM, That I do not understand is:

When I get this final tempDirection at the end and I send it back to my Ships Navigation computer to head towards it.... IT DOES NOT take into account the magnitudes of the two vectors. Or it does not appear to do this.

What I want to see happen is: As the ship begins to approach it's optimalrange. It is being affected by two vectors:

--(example1)The vector pointing (towards) or (awayFrom) the target.

--(example2)The vector that is a perfect perpendicular tangent to the sun/planet.

I want the vector in example1 to get weaker as we get closer to the optimalrange. And as a direct-inverse-result the example2 vector should get stronger (because i set it that way in part3). I DID prove that my math is correct for finding the strength values for these 2 vectors. But I do not know the mathematical function I need to apply to them.

Whenever I run this code and return this Vector3 back to my shipsNavigationComputer, it's always dead in the middle between the 2 Vectors. **It is not** scewed by the weight of their **magnitude**:

```
tempDirection = tempDirection + c;
```

# So what Mathematical Function am I needing to perform?

--It seems that adding vectors won't do it -- I have thought about DotProduct, but I have no Idea how to apply that to my configuration -- something Im missing?

**Answer** by tanoshimi
·
Feb 07, 2015 at 07:32 AM

Haven't studied in detail, but at first glance this looks wrong to me:

```
float calcX = (this.transform.position.x - myTarget.transform.position.x) - myTargetsRadius;
float calcY = (this.transform.position.y - myTarget.transform.position.y) - myTargetsRadius;
float calcZ = (this.transform.position.z - myTarget.transform.position.z) - myTargetsRadius;
distanceToTarget = Mathf.Sqrt (calcX*calcX + calcY*calcY + calcZ*calcZ);
```

Did you not mean:

```
Vector3 calc = (this.transform.position - myTarget.transform.position).normalized * myTargetsRadius;
distanceToTarget = Vector3.Distance(this.transform.position, calc);
```

? But agree with the other commenters - use Debug.Log and OnDrawGizmos to test what values your code is producing/plot them visually in the scene view.

**Answer** by karma0413
·
Feb 07, 2015 at 02:45 PM

# The Solution:

While I was testing the variables, I was working in the wrong section of code. This helped contribute to the problem because I was always in a case where I wouldn't see the changes. /BONK

Additionally, the other folks replying to my problem were in fact correct about the Debug.DrawRay. While, I thought I had enough drawRays on the screen; I actually was not showing the resulting drawRay each time I did a calculation and therefore was not completely understanding the processes taking place.

My calculations were in fact correct, and I haven't changed them. Well except for one minor problem. When I originally did the COUNTER-CLOCKWISE script. I did the inverse calculation of the result after all the changes. More correctly, when I do counter-clockwise I simply needed the INVERSE of the (LeftHand Rule) resulting vector. Now the mathematical inverse is done in the right location.

And to finally answer my own original question:

**YES,**: When you do an addition between two different Vector3 directions. Their magnitudes will automatically weight it's direction. So we can see here in the updated code I provide now:

We can see to obtain, the left-hand rule calculation ( this is called Cross Product multiplication ) we do the following:

```
if (orbitDirection == 1) // NORMAL CLOCK-WISE
{
// *** WARNING *** Unity uses the LEFT HAND RULE: http://docs.unity3d.com/ScriptReference/Vector3.Cross.html
Vector3 a = myTarget.transform.position - this.transform.position;
Vector3 b = this.transform.up;
Vector3 c = Vector3.Cross (a,b);
vectorTwo = c;
```

We already had VectorOne - which was simply go ( towards) or ( awayfrom ) depending if we were shallow of the orbiting optimal range, or if we had exceeded. And now we just found vectorTwo above.

The next thing to do was to define the strengths of each of these Vectors. For example if my optimal orbitting range is 400meters. Then I stated that if the ship was within 80% of that, then lets use this smoothed-navigation-guidance code as below:

```
float upperEndRange = optimalRange + (optimalRange * 0.80f);
float lowerEndRange = optimalRange - (optimalRange * 0.80f);
```

And Now we just simply find out the strengths. And to find out how much strength each vector gets; we define it in terms of 100% of how close or far we are from our optimal range. A float number that is between 0-100. [EDIT NOTE:] I could have simply divided the final result by/100 to get a number between 0-1.0. But I found it wasn't needed when computing the final destination direction.

tempStrength : is how much strength to go (towards) or (awayfrom) the target we are orbitting. Obviously is we are closer to the 80% limit on this. then tempStrength will be very near 100

cStrength : is the strength of the tangent Vector that is perpendicular to the object we are orbitting. And as a DIRECT-INVERSE-RELATIONSHIP ; whatever % of 100% is left from tempstrength. we can give it to cStrength. So the closer we are to our optimal range ; then the more cStrength = 100, and our tempStrength becomes close to 0.0

```
tempStrength = Mathf.Abs (optimalRange - distanceToTarget);
float ratio = 100/ (optimalRange - lowerEndRange); // so here is how we got that ratio multiplyer number... By basically putting it in an aspect in terms of percentage. /100
tempStrength = tempStrength * ratio; // .4166 ONLY if the upper end is 20% of 400 and lower end is 20% of 400, how did we get this number though...Explained one line up..
cStrength = 100 - tempStrength;
//vectorOne = vectorOne.normalized;
vectorOne = vectorOne * tempStrength;
//vectorTwo = vectorTwo.normalized;
vectorTwo = vectorTwo * cStrength;
tempDirection = vectorOne + vectorTwo;
```

Very Lastly: To find the COUNTER-CLOSEWISE... As I mentioned we just plug in the Inverse of Vector C; which was (looking back), the RESULT of a CrossProduct between Vector a and Vector b. So Now instead of facing LEFT-HAND... we actually turn right and go counter-clockwise (IF WE ARE FACING THE OBJECT)

```
if (orbitDirection == -1) //ACTUALLY COUNTER-CLOCKWISE
{
Vector3 a = myTarget.transform.position - this.transform.position;
Vector3 b = this.transform.up;
Vector3 c = Vector3.Cross (a,b);
vectorTwo = -c;
float tempStrength;
float cStrength;
tempStrength = Mathf.Abs (optimalRange - distanceToTarget);
float ratio = 100/ (optimalRange - lowerEndRange); // so here is how we got that ratio multiplyer number... By basically putting it in an aspect in terms of percentage. /100
tempStrength = tempStrength * ratio; // .4166 ONLY if the upper end is 20% of 400 and lower end is 20% of 400, how did we get this number though...Explained one line up..
cStrength = 100 - tempStrength;
//vectorOne = vectorOne.normalized;
vectorOne = vectorOne * tempStrength;
//vectorTwo = vectorTwo.normalized;
vectorTwo = vectorTwo * cStrength;
tempDirection = vectorOne + vectorTwo;
//tempDirection = tempDirection;
}
```

# Oooh, it's fancy, huh?

I figured you all might appreciate a screenshot of the result:

**Do: Control+MouseWheel to zoom into all of its fine glory!**

### Your answer

### Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.