﻿ Animancer - Vectors

# Vectors

Vector math is not part of C# itself, but is extremely common in Unity and game development in general. Vectors are simply groups of numbers and the most commonly used one in Unity is a `Vector3`:

``````public struct Vector3
{
public float x;
public float y;
public float z;
}
``````

There are also `Vector2` without the `z` field and `Vector4` with a `w` field.

Some places where vectors are used throughout Unity include:

Note that vectors store their values using `float`s (which can hold about 7 decimal digits of precision), but when converted to strings it rounds the values off to one decimal place to make them easier to read. So it is important to be aware that if for example you log the position of an object, it will only display a rounded value unless you specifically log `...position.x + ", " + position.y...`.

# Arithmetic

Simple arithmetic operations work similarly with vectors (`Vector2`, `Vector3`, and `Vector4`) as with individual numbers:

Op Parameters Returns
`+` `vector, vector` A `vector` with the values of the corresponding fields in each parameter added together.
`-` `vector, vector` A `vector` with the values of the corresponding fields in each parameter subtracted from each other.
`*` `vector, float` A `vector` with the values of the input `vector` each multiplied by the input `float`. This esentially multiplies its Magnitude by that value.
`/` `vector, float` A `vector` with the values of the input `vector` each divided by the input `float`. This esentially divides its Magnitude by that value.
`==` `vector, vector` `true` if each of the values of the input `vector`s are approximately equal, otherwise `false`. This is actually very unhelpful because it uses an entirely arbitrary threshold to define how close "approximately equal" is. The equality operator should be checking for equality, not approximate equality.

## Difference

One particularly useful property of vector subtraction is that it calculates the difference between two values, such as the offset from one position to another or the difference between the velocity of two objects. A vector going from `a` to `b` is calculated using `b - a`. For example:

Single Number Vector
``````float a = 2;
float b = 7;

float difference = b - a;
// difference = 5.
// So 5 is the "offset" between them.
// a + 5 will give b.
``````
``````Vector2 a = new Vector2(2, 6);
Vector2 b = new Vector2(7, 13);

Vector2 difference = b - a;
// difference = (5, 7).
// So (5, 7) is the "offset" between them.
// a + (5, 7) will give b.
``````

# Magnitude

If you think of a `Vector2` as a right-angled triangle where its `x` value is the length of one side and its `y` value is the length of another side, then you can calculate the length of the hypotenuse using the Pythagorean Theorem:

``````// 2D:
length = square root of (x * x + y * y)

// 3D:
length = square root of (x * x + y * y + z * z)
``````

This is the calculation performed by `Vector3.magnitude` and `Vector3.Distance` which are very useful for things like checking how far away something is from something else.

Unfortunately, the square root operation required to calculate the magnitude of a vector is quite complex and takes much longer to execute than simple arithmetic. In some situations, this can be avoided by using the Squared Magnitude instead. For example:

• If you want to display the distance to a destination as text, then you obviously need to calculate the proper distance.
• But if you just want to know whether that destination is within a certain range, you can square the range and compare it to the squared distance like so: `if ((target - start).sqrMagnitude < range * range)`

# Normalization

A Unit Vector is a vector with a length of 1 unit. Setting the length of a vector to 1 without changing its direction is called "normalization" and can be done using `Vector3.Normalize` to modify a vector or `Vector3.normalized` to get a normalized copy of it. Normalization simply divides a vector by its Magnitude, so if you have already calculated the `magnitude` you can do the division yourself to avoid the performance cost of recalculating it.

# Dot Product

The `Vector2.Dot` method performs the following calculation:

``````public static float Dot(Vector2 lhs, Vector2 rhs)
{
return lhs.x * rhs.x + lhs.y * rhs.y;
// Vector3 has the same thing with the z values as well.
}

// "lhs" is short for "left hand side".
// For example, in an operation like "x + y", the "x" is the "left hand side" of the operation.
// This is common mathematical terminology, but is not particularly helpful as a parameter name.
// The parameters might as well just be called "a" and "b".
``````

Calculating the dot product of two vectors tells you how similar their directions are:

• If both input vectors are Normalized, the result will be between 1 and -1:
• 1 means both vectors have the same direction.
• 0 means they are perpendicular (90 degrees apart).
• -1 means they are pointing in opposite directions.
• This is part of the calculation used in `Vector2.Angle` to calculate the actual angle between two vectors.
• If one of the input vectors is Normalized, the result will tell you how much of the other vector lies in that direction. The Directional Blending example uses this to find out how much of a movement direction vector lies in the direction of the object's right and forward axes individually to control its animation blending along each axis.
• If they are not Normalized, the result will range from their magnitudes multiplied together to that same value as a negative. This raw value is less useful for anything other than checking whether they are more or less than 90 degrees apart (based on whether the result is positive or negative).

# Raycasting

The `Physics.Raycast` method allows you to check if a particular line through 3D space (a ray) intersects with any physics objects (objects with `Collider` components).

You can cast a ray from any origin point in any direction you want, for example:

• Cast from the head of an enemy towards the player to determine if that enemy can see the player.
• Cast downwards from a character's feet with a very short `maxDistance` to determine if they are on the ground.
• Cast from the camera in the direction of the mouse cursor to find out what the player clicked on. The `Camera.ScreenPointToRay` method makes it very easy to convert a screen position into a `Ray` containing an `origin` and `direction` to use in a raycast.

## Debug Lines

Raycasts have no visual appearance by default, so it can be useful to draw lines in the Scene view to help with debugging.This can easily be done using `Debug.DrawLine` and `Debug.DrawRay` which are practically the same method except that `DrawLine` takes an `end` parameter to specify the exact end point while `DrawRay` takes a `direction` parameter and calculates the end point as `start + direction`.

Lines will only appear for one frame by default so you can use the `duration` parameter to specify how long you want it to remain for. They are not visible in the Game window or in a runtime build, only in the Scene window in the Unity Editor.

The following example performs a raycast every frame and uses some lines to visualise the result in the scene view:

``````using UnityEngine;

public sealed class RaycastVisualisationExample : MonoBehaviour
{
private void Update()
{
const float MaxDistance = 100;

// Get a ray where the mouse cursor is pointing.
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);

RaycastHit raycastHit;

// Raycast from there.
// If it hits something, the Raycast method will return true.
// And the "out raycastHit" will output the results of what it hit.
if (Physics.Raycast(ray, out raycastHit, MaxDistance))
{
// Draw a green line from the start of the ray to the point it hit.
// Note: this is DrawLine so it takes a start and end point.
Debug.DrawLine(ray.origin, raycastHit.point, Color.green);

// The "normal" is a unit vector that tells us which way the surface is facing.
// Draw a blue line from the hit point in the direction of the normal.
// Note: this is DrawRay so it takes a start point and direction.
Debug.DrawRay(raycastHit.point, raycastHit.normal, Color.blue);
}
else
{
// If the ray did not hit anything, draw a red line out to its max range.
Debug.DrawRay(ray.origin, ray.direction * MaxDistance, Color.red);
}
}
}
`````` 