# Vector Maths with Unity Gizmos

It’s really nice to get a game finally published. Endless Elevator is now on the Google Play Store so I’ve been planning and experimenting and just plain playing around with Unity and Game Ideas before I start a new project. It’s kind of like a holiday.

I like maths and I also like visualising it with Unity. This little project is one of the simplest types of maths that is generally associated with game programming and that’s adding and subtracting vectors and getting the distance between two vectors.

These sorts of functions are endlessly useful. They answer questions like: How far away is my target? Is my Player going to fall off the platform? Can I jump between two platforms? And so on and so on.

What I like about this one is that it highlights two things. 1. The difference between a player and a target’s perspective (in this project I nominate the circle as the player and the cylinder as the target), and 2. calculating the magnitude or distance between them.

To calculate the distance (magnitude) between two points you take the square root of the square of the x and y values. Which sounds a little complicated but is really just making a square the size and length of your x, and adding that to a square the size of your y, and then getting the square root of the total size of that square.

This is how it looks in the Scene View:

The project is really easy to set up. All you need is an Empty Game Object to hold the script and two other objects. I used a Capsule and a Sphere. Drag the two objects into the public Transform components on the script.

Here is the reproduced script below:

``````using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor.UI;

public class GridGizmo : MonoBehaviour
{

public Transform circle;
public Transform capsule;
public Vector3 differenceToCapsule;
public Vector3 differenceToCircle;
public float magnitude;

void Update()
{
differenceToCapsule = capsule.position - circle.position;
differenceToCircle = circle.position - capsule.position;
/*
Magnitude of a Vector (Length of the Vector)
We use Pythagoras' theorem to calculate it:
|a| = √( x2 + y2 )
*/
magnitude = Mathf.Sqrt(Mathf.Pow(differenceToCapsule.x, 2) + Mathf.Pow(differenceToCapsule.y, 2));
}

public void OnDrawGizmos()
{

// Grid Number Labels
for (int i = -10; i < 11; i++)
{
UnityEditor.Handles.Label(new Vector3(0f, i, 0f), "" + i);
}

for (int i = -20; i < 21; i++)
{

UnityEditor.Handles.Label(new Vector3(i, 0f, 0f), "" + i);
}

// Labels of Objects
UnityEditor.Handles.Label(new Vector3(circle.position.x + 1, circle.position.y, circle.position.z), "POSI: " + circle.transform.position);
UnityEditor.Handles.Label(new Vector3(circle.position.x + 1, circle.position.y - 0.5f, circle.position.z), "DIFF: " + differenceToCapsule);
UnityEditor.Handles.Label(new Vector3(circle.position.x + 1, circle.position.y - 1f, circle.position.z), "Magnitude: " + magnitude);

UnityEditor.Handles.Label(new Vector3(capsule.position.x + 1, capsule.position.y, capsule.transform.position.z), "POSI: " + capsule.transform.position);
UnityEditor.Handles.Label(new Vector3(capsule.position.x + 1, capsule.position.y - 0.5f, capsule.transform.position.z), "DIFF: " + differenceToCircle);

// The line
Gizmos.color = Color.blue;
Gizmos.DrawLine(circle.position, capsule.position);
}
}
``````

As I mentioned above I do like mathy things in Unity. Here are some of the other one’s I’ve done which are a bit more complicated. I find them really really useful to cement those ideas that I should know back to front but always forget exactly how they work.

# Unity: Circular Movement with Triangles

My son asked to do some game programming with me last week. I was super excited. We did an eyeball rolling around in a circular motion (see image below). He did everything from working in Unity to making the assets and materials and I was very proud. I helped with the function to make it circle. It got me thinking how to explain circular movement and the use of Pythagorean triangles and cos and sin functions. They are simple maths but kind of hard to explain without a picture so hence this project about making circles with triangles.

## The Basic Idea

To simplify I’ll work in 2D so we only got two Axis. X and Y. The Center of our circle will be on the 0 (zero, zero). So we could think of this as a co-ordinate system with two planes. If we were mathematicians we would call this a Cartesian Plane after Rene Descartes but being a Game Developer with Unity I’m going to call it the Scene view in 2D.

Our circle is defined by it’s Radius (ie. the distance from the Center).

On each Update() event our GameObject gets a new X,Y position on the Radius of the circle.

## The Angle of Change

To start with we work out what the angle of difference is between this Update and the last one. The time passed during that period is known as the DeltaTime. Our “speed” is how many Radians we are travelling around the circle in that time. A radian is the length of the radius laid around the circumference of the circle. We multiply the Speed (how fast we are ticking through the radians) by the DeltaTime (time passed since last Update) to tell us that angle size.

# angleInRadians += RotateSpeed * Time.deltaTime;

## Convert Polar to Cartesian

After working out the angle we have what is called a Polar Coordinate. That is we define our location by how far away it is (the distance – in this case as it’s a circle it’s always the same i.e. the radius), and what the angle (θ) is. Now we need to convert between that definition of a location in the Scene View to another one we can use in the Unity move function.

This is where Pythagoras and right angled triangles comes in – to convert from Polar Coordinates (r,θ) to Cartesian Coordinates (x,y) we use cos and sin :
x = r × cos( θ )
y = r × sin( θ )

In Unity there is already a function that does this:

But what does this really mean? Cos and Sin are just numbers. They represent the relationship between two sides of the triangle.

For example cos is the value of the relationship between the side of the triangle that is adjacent to the angle (the side next to the angle) and the hypotenuse (the long side on the other side of the angle). We are going to use cos to find the x value (how far along the horizon it is) in our Vector2 position. The same way we use Sin to find the y position (how far up or down).

In the image below see how there are squares built off each side of the triangle. Pythagorean theory for right angled triangles states that the area/volume of the two squares built of the two smaller sides will be equal to the area/volume of the big square built off the longest (hypotenuse) side of the triangle.

The big blue square has a volume of 1 because the radius of the circle is 1 unit on the Cartesian plane and One Squared is One. The volume of the other two squares (Magenta and Yellow) will always add up to one. Their volumes added together will always equal the volume of the blue square. This is the Pythagorean theory of right angled triangles in action. The length of a side of the Yellow box is the x value and the length of a side on the Magenta box is the y value. That’s our current position in (x, y) format which we can pass to the transform.position function.

The two images below show two Updates() that are reasonably close together so you can see in detail and in “freeze frame” what’s going on between the Updates() with all the variables. You can see the angle go from about 8 degrees to 20 degrees and the changing values for sin and cos which result in changing (x,y) values and volumes of the squares.

That’s basically it apart from some modifications to the values for being on the negative sides of the circle.

The script attached to the moving object is below but I’ve also put it on github here: https://github.com/zuluonezero/MoveInACircleWithTriangles

I’m finding it deeply satisfying to watch the triangles and squares get used to define a circle going round over and over again.

If this sort of thing floats your boat I’ve done some other posts on making curves using intersecting lines:

http://www.zuluonezero.net/2019/06/04/unity-2d-curves-using-triangles/

Also on using sin to use curves in movement: http://www.zuluonezero.net/2018/06/20/fly-birdy-fly-2d-curved-movement-in-unity/.

``````using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEditor;
public class CircleMe : MonoBehaviour
{
public float RotateSpeed = 5f;      // How fast we move through the radians
public float Radius = 0.1f;         // How "deep" the circle is
public Vector2 centreOfCircle;      // The Centre of our circle
public float angleInRadians;        // The angle (in radians) between our position between one update and the next
// A radian is the angle created if the length of the radius
// is laid along the circumference of the circle (about 57.2958 degrees)
public Vector2 newPosition;         // The new position for every new Update event
public Text displayText;
public float angleInDegrees;
private LineRenderer triLine;
private Vector3 centre;
private Vector3 yLoc;
public float angle4Display;
private Vector3 sq1;
private Vector3 sq2;
private Vector3 sq3;
private Vector3 sq4cyan1;
private Vector3 sq4cyan2;
public Vector2 slopecyan;
public Vector2 p1cyan;
public Vector2 p2cyan;
private void Start()
{
centreOfCircle = transform.position;
// (0, 0) but could be anywhere
centre = transform.position;
}
private void Update()
{
{
}
// eg.       0 += 5 * 0.25  (answer is 1.25)    // if deltaTime was 0.25 of a second
// and our initial angle was 0 radians.
// Remember += is short for x = the current value of x plus itself (x = x + x)
// we need to convert the angle and radius into an x, y position
// (x, y)   =            (0.9997, 0.0218) * 0.1
// (x, y)   =            (0.09997, 0.00218)
transform.position = centreOfCircle + newPosition;   // Adding Vectors
// (0.09997, 0.00218) = (0, 0) + (0.09997, 0.00218)
// this is our starting (x, y) position
// Now do it again for the next Update - the code below has been duplicated for this example
/*
// eg.       1.25 += 5 * 0.25  (answer is now 1.25 + 1.25 = 2.5)    // if deltaTime was 0.25 of a second
// (x, y)   =            (0.99904, 0.0436) * 0.1
// (x, y)   =            (0.09990, 0.00436)
transform.position = centreOfCircle + newPosition;   // Adding Vectors
// (0.09990, 0.00436) = (0, 0) + (0.09990, 0.00436)
*/
if (transform.position.x > 0)
{
yLoc = new Vector3(centre.x + Radius, centre.y, centre.z);
}
else
{
yLoc = new Vector3(centre.x - Radius, centre.y, centre.z);
}
}
public void OnDrawGizmos()
{
Gizmos.color = Color.blue;
// Yellow square
Gizmos.color = Color.yellow;
sq1 = new Vector3((transform.position.x / 2), (transform.position.x / 2f), 0f);
if (transform.position.x > 0)
{
if (transform.position.y > 0)
{
Gizmos.DrawWireCube(new Vector3((transform.position.x / 2), -(transform.position.x / 2f), 0f), new Vector3((transform.position.x), (transform.position.x), (transform.position.x)));
Handles.Label(new Vector3((transform.position.x / 2), -(transform.position.x / 2f), 0f), "Vol: " + (transform.position.x * transform.position.x));
}
else
{
Gizmos.DrawWireCube(sq1, new Vector3((transform.position.x), (transform.position.x), (transform.position.x)));
Handles.Label(sq1, "Vol: " + (transform.position.x * transform.position.x));
}
}
else
{
if (transform.position.y > 0)
{
Gizmos.DrawWireCube(sq1, new Vector3((transform.position.x), (transform.position.x), (transform.position.x)));
Handles.Label(sq1, "Vol: " + (transform.position.x * transform.position.x));
}
else
{
Gizmos.DrawWireCube(new Vector3((transform.position.x / 2), -(transform.position.x / 2f), 0f), new Vector3((transform.position.x), (transform.position.x), (transform.position.x)));
Handles.Label(new Vector3((transform.position.x / 2), -(transform.position.x / 2f), 0f), "Vol: " + (transform.position.x * transform.position.x));
}
}
// Magenta square
Gizmos.color = Color.magenta;
sq2 = new Vector3((transform.position.y / 2), (transform.position.y / 2f), 0f);
if (transform.position.x > 0)
{
if (transform.position.y > 0)
{
Gizmos.DrawWireCube(new Vector3((transform.position.x + transform.position.y / 2), (transform.position.y / 2f), 0f), new Vector3((transform.position.y), (transform.position.y), (transform.position.y)));
Handles.Label(new Vector3((transform.position.x + transform.position.y / 2), (transform.position.y / 2f), 0f), "Vol: " + (transform.position.y * transform.position.y));
}
else
{
Gizmos.DrawWireCube(new Vector3((transform.position.x + Mathf.Abs(transform.position.y) / 2), (transform.position.y / 2f), 0f), new Vector3((transform.position.y), (transform.position.y), (transform.position.y)));
Handles.Label(new Vector3((transform.position.x + Mathf.Abs(transform.position.y) / 2), (transform.position.y / 2f), 0f), "Vol: " + (transform.position.y * transform.position.y));
}
}
else
{
if (transform.position.y > 0)
{
Gizmos.DrawWireCube(new Vector3((transform.position.x - transform.position.y / 2), (transform.position.y / 2f), 0f), new Vector3((transform.position.y), (transform.position.y), (transform.position.y)));
Handles.Label(new Vector3((transform.position.x - transform.position.y / 2), (transform.position.y / 2f), 0f), "Vol: " + (transform.position.y * transform.position.y));
}
else
{
Gizmos.DrawWireCube(new Vector3((transform.position.x + transform.position.y / 2), (transform.position.y / 2f), 0f), new Vector3((transform.position.y), (transform.position.y), (transform.position.y)));
Handles.Label(new Vector3((transform.position.x + transform.position.y / 2), (transform.position.y / 2f), 0f), "Vol: " + (transform.position.y * transform.position.y));
}
}
// Red Triangle
Gizmos.color = Color.red;
Gizmos.DrawLine(centre, new Vector3(transform.position.x, centre.y, centre.z));
Gizmos.DrawLine(new Vector3(transform.position.x, centre.y, centre.z), transform.position);
Gizmos.DrawLine(transform.position, centre);
if (transform.position.x > 0)
{
if (transform.position.y > 0)
{
Gizmos.DrawLine(new Vector3(transform.position.x - 0.1f, 0f, 0f), new Vector3(transform.position.x - 0.1f, 0.1f, 0f));
Gizmos.DrawLine(new Vector3(transform.position.x - 0.1f, 0.1f, 0f), new Vector3(transform.position.x, 0.1f, 0f));
}
else
{
Gizmos.DrawLine(new Vector3(transform.position.x - 0.1f, 0f, 0f), new Vector3(transform.position.x - 0.1f, -0.1f, 0f));
Gizmos.DrawLine(new Vector3(transform.position.x - 0.1f, -0.1f, 0f), new Vector3(transform.position.x, -0.1f, 0f));
}
}
else
{
if (transform.position.y > 0)
{
Gizmos.DrawLine(new Vector3(transform.position.x + 0.1f, 0f, 0f), new Vector3(transform.position.x + 0.1f, 0.1f, 0f));
Gizmos.DrawLine(new Vector3(transform.position.x + 0.1f, 0.1f, 0f), new Vector3(transform.position.x, 0.1f, 0f));
}
else
{
Gizmos.DrawLine(new Vector3(transform.position.x + 0.1f, 0f, 0f), new Vector3(transform.position.x + 0.1f, -0.1f, 0f));
Gizmos.DrawLine(new Vector3(transform.position.x + 0.1f, -0.1f, 0f), new Vector3(transform.position.x, -0.1f, 0f));
}
}
// Cyan Square
Gizmos.color = Color.cyan;
if ((transform.position.x > 0 && transform.position.y > 0) || (transform.position.x < 0 && transform.position.y < 0))
{
slopecyan = new Vector2(transform.position.x, transform.position.y);
p1cyan = new Vector2((transform.position.x - slopecyan.y), (transform.position.y + slopecyan.x));
p2cyan = new Vector2((centre.x - slopecyan.y), (centre.y + slopecyan.x));
Gizmos.DrawLine(transform.position, p1cyan);
Gizmos.DrawLine(centre, p2cyan);
Gizmos.DrawLine(p1cyan, p2cyan);
}
else
{
slopecyan = new Vector2(transform.position.x, transform.position.y);
p1cyan = new Vector2((transform.position.x + slopecyan.y), (transform.position.y - slopecyan.x));
p2cyan = new Vector2((centre.x + slopecyan.y), (centre.y - slopecyan.x));
Gizmos.DrawLine(transform.position, p1cyan);
Gizmos.DrawLine(centre, p2cyan);
Gizmos.DrawLine(p1cyan, p2cyan);
}
Vector3 lbl = new Vector3((p1cyan.x / 2), (p1cyan.y / 2), 0f);
// Angle Marker
if (transform.position.y > 0)
{
if (transform.position.x > 0)
{
angle4Display = angleInDegrees;
Handles.DrawSolidArc(centre, Vector3.forward, yLoc, angle4Display, 0.25f);
}
else
{
angle4Display = -(angleInDegrees - 180f);
Handles.DrawSolidArc(centre, Vector3.forward, transform.position, angle4Display, 0.25f);
}
}
else
{
if (transform.position.x < 0)
{
angle4Display = (angleInDegrees - 180f);
Handles.DrawSolidArc(centre, Vector3.forward, yLoc, angle4Display, 0.25f);
}
else
{
angle4Display = -(angleInDegrees - 360f);
Handles.DrawSolidArc(centre, Vector3.forward, transform.position, angle4Display, 0.25f);
}
}
// Labels
Handles.color = Color.blue;
Handles.Label(centreOfCircle, angle4Display.ToString());
Handles.color = Color.white;
Handles.Label(transform.position, "X: " + System.Math.Round(transform.position.x, 2) + " Y: " + System.Math.Round(transform.position.y, 2));
// sin opposite/hypotenuse
Handles.Label(new Vector3(1.2f, 0.8f, 0f), "sin opposite/hypotenuse");
Handles.Label(new Vector3(1.3f, 0.7f, 0f), "sin: " + Vector3.Distance(centre, (new Vector3(transform.position.y, 0f, 0f))) / Vector3.Distance(centre, (transform.position)) );
Handles.Label(new Vector3(1.2f, 0.6f, 0f), "cos adjacient/hypotenuse");
Handles.Label(new Vector3(1.3f, 0.5f, 0f), "cos: " + Vector3.Distance(centre, (new Vector3(transform.position.x, 0f, 0f))) / Vector3.Distance(centre, (transform.position)));
Handles.Label(new Vector3(1.2f, 0.4f, 0f), "tan opposite/adjacient");
Handles.Label(new Vector3(1.3f, 0.3f, 0f), "tan: " + Vector3.Distance(centre, (new Vector3(transform.position.y, 0f, 0f))) / Vector3.Distance(centre, (new Vector3(transform.position.x, 0f, 0f))));
Handles.Label(new Vector3(1f, -0.3f, 0f), "Next Position on Update()");
Handles.Label(new Vector3(1f, -0.6f, 0f), "" + Mathf.Cos(angleInRadians) + ", " + Mathf.Sin(angleInRadians) + " * "  + Radius + " = " + newPosition);
}
}
/*
Using Cartesian Coordinates we mark a point by how far along (x) and how far up (y) it is:
Using Polar Coordinates we mark a point by how far away (magnitude or in this case as it's a circle always the radius is the same), and what angle (θ) it is:
To convert from Polar Coordinates (r,θ) to Cartesian Coordinates (x,y) :
x = r × cos( θ )
y = r × sin( θ )
Example: add the vectors a = (8,13) and b = (26,7)
c=a+b
c= (8,13) + (26,7) = (8+26,13+7) = (34,20)
*/
``````

# Unity Code Review and Style Guide

Hi Trixie here. It’s Code Review time! Yay. Time to clean up that code and start really looking at all the crap work you’ve done over the last months and clean that sh!t up!

I’ll post our in-house Style Guide (which of course goes out the window when you are coding in anger) at the bottom of the post. Hopefully someone else will follow it or find it useful.

This is how the code review works:

• Make a list of all your scripts and the game objects they are attached to.
• Go through all the variables/functions/iterators and make them follow the standard in the Style Guide (which includes making logical names sensible to humans).
• Check all your Public references and make Private if you are really not using them.
• Trawl the console output and clean up the extraneous debugging guff.
• Start grouping your code into functions that do a similar thing and try and make them standardised.
• If you are lucky you will find some optimisations in there as well to make your game run faster, better, more efficient, lighter.

Then at least it will be another few months before you muck it up again.

I know there are automated tools to do some of this work but I prefer to work though my own methods. I like to have complete control over the process. My favourite tool for analysis is the Unix Command line (I know weird right?). My workstation is Windows 10 but I have a Cygwin like utility called MobaXterm installed which allows me to interrogate the file system like a Unix machine and use grep and other commands on all the files that make up my scripts.

Basically I want to build a big spreadsheet of information that lists all my scripts and the Game Objects they attach to and the Public interfaces and variables etc.

This is one that I started for Endless Elevator:

Then I start extracting Game Objects and Code loops using the Unix Command Line so I can start to build a picture of what’s going on.

One of the outcomes of this process is that I want to be left with a map of how stuff works that I can connect the dots on in the future. It’s kind of like a Design Document in reverse.

Here are a few examples of the commands I’m using and how the information is extracted:

# grep bool *.cs # Getting out all my bools – I tend to use true or false tests a lot to explicitly define functions and events.

As you can see above the bool names are mostly descriptive and the variable name is mostly in camelCase. Those few like swingme will get updated to swingMe and the overly generic “yes” and “yesNow” (what was I thinking!) will be made more descriptive of what we are really agreeing to in that code.

This command looks at all the sort of functions I am using and where. It’s nice to know which one’s don’t have an Update() function and where all my Collisions and Triggers are.

# egrep “{|}” AI.cs # I use something like this to collect an idea of the complexity of my loops and functions.

# egrep “{|}(|)|if|for|else” AI.cs # This is my favourite type of command. Like the command above I use it for working out the structure of a script. This is way easier than scrolling through lines and lines of code and comment and makes it really easy to spot areas where you have gone loopy crazy pants.

# grep GameObject *.cs # This one makes a good list of all the scripts that I reference another Game Object in. It helps build a visual map of what dependencies there are between objects.

# grep script *.cs # This one does a similar thing in that it grabs all the times that I am calling something from within another script attached to another Game Object..

The command line is also a nice quick way to check how many lines of code you have written.

There are some good Style Guides out there.

I like this one for it’s organised folder structure and naming convention for files: https://github.com/stillwwater/UnityStyleGuide

I like the Microsoft C# one for layout and block style: https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions

I like this for it’s use of camelCase and Capitals and it’s preferred block style: https://github.com/raywenderlich/c-sharp-style-guide

As a basic guide though I always try and mimic the Unity API manual. For example this page for OnCollisionEnter:

``````// A grenade
// - instantiates an explosion Prefab when hitting a surface
// - then destroys itself
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
public Transform explosionPrefab;
void OnCollisionEnter(Collision collision)
{
ContactPoint contact = collision.contacts[0];
Quaternion rotation = Quaternion.FromToRotation(Vector3.up, contact.normal);
Vector3 position = contact.point;
Instantiate(explosionPrefab, position, rotation);
Destroy(gameObject);
}
}``````

The comments are appropriate. The Class name uses a Capital for each word. The curly brackets are on a new line and indented block space. Varables are in camelCase.

Here is our minimal Style Guide. This is the basics of how we roll things:

Thanks for reading. See you all in the New Year… Trixie.

# Unity Audio vs Wwise

To start with I wanted to do a general investigation into Wwise the integrated audio package for Unity by AudioKinetic. When I started working through it I figured it would be more interesting to look at Wwise in comparison to Unity’s own audio API and mixer components which have been around since Unity 5.

To do that I’m going to compare a game in three different builds. Build one is it’s original state with simple scripts that run an AudioSource.Play() method. The Second build I will add another layer of complexity by using the Unity built in Mixer and see if there are any differences or advantages. Lastly I’ll redo the project with the Wwise API and investigate how that impacts build size and project complexity and weigh it up against the previous two builds. Mostly I’m looking for difference in performance between the three builds, build size and complexity, and weighing that up against ease of implementation and flexibility.

I refreshed an old project called “MusicVisualiser”that I started for my Five Games in Ten Weeks Challenge. The game is like a singing solar system. There is a bunch of “planets” in the night sky that play a set piece of music when clicked. It’s a really simple concept and project but I think it will work for this comparison as the parameters can be limited to just a few audio tracks but we can play with spacing and roll-off and other advanced audio features.

Let’s have a look at the game first.

These “planets” are simple native Unity sphere meshes with an Audio Source component and a particle system that’s triggered when it’s clicked. You can see in the Audio Source that we are not using a Mixer for Output and all the Audio sources compete for resources and play at their default volume and priority.

The PlayMe script just takes in the AudioSource and plays it:

``````   public AudioSource my_sound;
if (Input.GetMouseButtonDown(0))
{
RaycastHit hitInfo;
target = GetClickedObject(out hitInfo);
if (target != null && target.name == my_name)
{
_mouseState = true;
screenSpace = Camera.main.WorldToScreenPoint(target.transform.position);
offset = target.transform.position - Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, screenSpace.z));
my_sound.Play();   // This is the Audio Component!
var expl1 = GetComponent<ParticleSystem>();
expl1.Play();
}
}``````

Pretty simple right. This is what the project looks like in the Profiler when it’s running and being actively engaged with. At that point we are looking at two Audio Sources are playing:

This is the build size from the Editor Log with our Audio Files broken out:

Build Report (Audio.Play)
Uncompressed usage by category:
Textures 0.0 kb 0.0%
Meshes 0.0 kb 0.0%
Animations 0.0 kb 0.0%
Sounds 547.5 kb 1.4%
Other Assets 1.4 kb 0.0%
Levels 38.3 kb 0.1%
Scripts 941.9 kb 2.4%
Included DLLs 3.9 mb 10.2%
Complete size 38.6 mb 100.0%

Used Assets and files from the Resources folder, sorted by uncompressed size:
204.3 kb 0.5% Assets/SomethingLurks_AAS.wav
164.5 kb 0.4% Assets/Step2Down_AAS.wav
136.9 kb 0.3% Assets/Underwater_AAS.wav
41.8 kb 0.1% Assets/M1_M12_37_ThumPiano_Aflat1.wav

## Unity Audio with Mixer

Now we add in the Mixer component to the project:

Then add a couple of Channels to the Mixer to split the audio between left and right. Then the Audio Sources are dropped into one or another of the Mixer Channels:

Next for bit more interest I added some effects in the Mixer. Here is where we see the advantages of using the Unity Mixer. Sounds can be manipulated in complex ways and the Audio Output chain be defined with presets and levels etc.

If we have a look at our Profiler while running with the new component we cannot really see any great differences. The ‘Others’ section of the CPU Usage is a bit higher and the Garbage Collector in the Memory is pumping regularly but the Audio Stats look pretty much unchanged:

Mind you this is a fairly low utilising game so we might get wildly different stats if we were really putting the system under the pump but I’m not performance testing here just comparing run states between the two builds.

Next if we build the game and have a look at the Editor Log the only thing that’s changed here is that the “Other Assets” size is a KB higher (Complete size has not been changed):

Build Report (Mixer)
Uncompressed usage by category:
Textures 0.0 kb 0.0%
Meshes 0.0 kb 0.0%
Animations 0.0 kb 0.0%
Sounds 547.5 kb 1.4%
Other Assets 2.3 kb 0.0%
Levels 38.3 kb 0.1%
Scripts 941.9 kb 2.4%
Included DLLs 3.9 mb 10.2%
Complete size 38.6 mb 100.0%

## Unity with Wwise

Next we are going to add Wwise to the Project. This is the basic workflow. In the Wwise Launcher we register our project and on the first tab we are presented with three Hierarchies.

The Master-Mixer Hierarchy – does what it says.
The Actor-Mixor Hierarchy – where most of your game audio develops (use the SoundSFX defaults).
Interactive Music Hierarchy – other stuff we won’t get into.

The next tab along is the events tab where you link your audio to game events. You can define your event here (use the default work unit).
Once you got the event there you can associate the event with the audio in the Action List.

Next you generate a SoundBank with Wwise that includes your audio and the code for the API calls to trigger sounds. You export that SoundBank into your game engine and link up the calls in your code.

## To Get Started with Wwise

To get started make an account with Audiokinetic and download the Wwise Launcher. The Integration package for Unity can be downloaded and installed directly from the WWise Launcher.

In the Wwise Launcher there is a WWISE tab that you can install and start the application from. Once you open it up you need to register your project within the launcher so Wwise can track you 🙂 ( click on the key icon next to your Wwise project and select ‘Register your Project to obtain a License’). Wise will run in Trial mode which restricts the SoundBank content to 200 media assets and cannot be used for Commercial purposes. Pricing for licensing is on their site but this is not a sales piece so if you want it you can look it up.

There are a bunch of plugins by Audiokinetic and their partners available and also Community offerings like AudioRain a dedicated rain synth with 60 procedurally generated presets for rain. What’s not to love about that!

There is a Wwise SDK for authoring your own plugins and a Wwise API which allows you to integrate into any engine, tool or application.

Audiokinetic do certifications that covers audio integration workflows,
mixing virtual soundscapes, working with sound triggering systems, and performance optimisation :
https://www.audiokinetic.com/learn/certifications/

Basically in Wwise you let the Launcher do all the setting up for you. You will install the Wwise binaries from here and manage your platform versions. Projects can be integrated here and if you don’t have the necessary plugins installed the Wwise Launcher will install them for you.

That’s basically it for the set up of Wwise and Integration with your Project. Next up we will have a look at what this has done to the Unity Console.

### Wwise in Unity

First thing we see is a bunch of errors that can be safely ignored. As we did not perform any configuration of our project in Wwise with audio files and events there was no SoundBank to generate yet.

In the Unity Console we have a new tab in our editor. The Wwise Picker Tab contains all the elements of the Wwise project that have been imported with the project integration. There is also a Wwise Global Game Object in the Unity Hierarchy and all the Wwise folders in the Assets folder.

Under the Component pull down there is a whole slew of Ak (AudioKinetic) options.

I know there has been a lot of “show and tell” in this post but I’m going to keep going and show the process of importing the audio into the Wwise Project, creating Events, and Generating the SoundBank.

### Working in Wwise

In the Wwise Project Explorer I right click on the Default Work Unit and import the audio files that were part of my project. (I’ve stripped the raw files out of my project for now and removed all the Mixer components and etc.).

Finally a SoundBank is generated from which the Unity project can access the sound files through the AudioKinetic API.

### Wwise Audio in Unity

When we go back to our Unity Editor and Refresh the Project and Generate SoudBanks we are presented with the following in the Wwise Picker. We can now access these files and and drag them on to our game objects directly. It’s that simple. Drag a sound from the Picker onto a Game Object and it automagically creates a component that is immediately accessible from within the editor.

Below the Play_Underwater_AAS event and audio file has been added to the Sphere Game Object.

The Trigger, Actions, and Callbacks can all be configured and access through the API. In my case I easily integrated the functionality I wanted with only one line change to my attached PlayMe.cs script that we looked at above. So now instead of my audio coming from the AudioSource component referenced by my_sound the audio is played by the AKSoundEngine.PostEvent.

``````            //my_sound.Play();
AkSoundEngine.PostEvent("Play_Underwater_AAS", this.gameObject);``````

Actually getting Wwise installed and set up and integrated with my Project was very very easy but not without bumps. It takes a very long time for packages to download and I had a bit of trouble upgrading my Wwise Launcher from an old version (it got stuck! and I had to remove it by hand and re-install). When I did have issues I got some very excellent help from AudioKinetic and after logging a case was emailed directly by a real person (which honestly was so surprising and wonderful to get that kind of support from a company when I’m on a trial license with no formal support agreement or rights).

So lets have a look at the differences in performance and package size. The first thing you notice with the Profiler below is that there is very little difference in performance but we can no longer see our audio stats as it’s been abstracted away from the Unity Engine. The Graph still shows the resources being used by Audio and the Total Audio CPU seems to be up to a third lower than the native Unity Audio statistics. It looks like it’s being clamped at just over 1.2. MB instead of regular peaks over 3 MB.

The Build Report is only a couple of MB larger for the total project size:

Build Report
Uncompressed usage by category:
Textures 0.0 kb 0.0%
Meshes 0.0 kb 0.0%
Animations 0.0 kb 0.0%
Sounds 0.0 kb 0.0%
Other Assets 7.3 kb 0.0%
Levels 38.5 kb 0.1%
Scripts 1.3 mb 3.1%
Included DLLs 3.9 mb 9.7%
Complete size 40.5 mb 100.0%

Basically a 2 MB difference! The Sounds have been extracted away as a file in the Build Report and we assume they are now part of “Other Assets” above.

I’m kinda blown away by how how little additional file size there is to the build considering the additional libraries code and available complexity that Wwise adds. There is literally a plethora of options and effects that we can play with in the Wwise package. It’s a bit like the excitement I got after the install of my first real Audio DAW. The scope is part boggling and part fantastical wonder at where we can go next. (Audio does get me unusually stimulated but that’s to be expected and tempered accordingly).

The questions I wanted to answer with this whole experiment was 1. Would including an audio middleware like Wwise make my Project more complex and difficult to manage? 2. Would the added Package make my build much larger? and 3. Would the performance of the Audio package be as good as the simple Unity Audio API? The answers are: No. No, and Yes. So I’m pretty happy with that and if the cost point of using the licensed version of Wwise is balanced out against the advantages of using it in the total cost of the Project then I would most definitely one hundred percent go for it.

# Why Normalize()

I’ve been doing some work on the AI for enemy behaviours for an unreleased game Endless Elevator and have been delving into the book “Unity 2018 Artificial Intelligence Cookbook – Second Edition” by Jorge Palacios.

It uses the Normalize() function regularly to record the direction of an object in relation to another object and it got me thinking about the usefulness of this function.  You can see why something like knowing the direction of the Player could be good for an enemy AI behaviour but I wanted to investigate more deeply about how this worked and how I could use it.

One of the things I hadn’t consciously been aware of, but is obvious once you point it out, is that a Vector3 can define a location (ie. a point in space 0, 0, 0) but it can also define a direction if you have a starting position and a target position.

A good example of a Vector being used to denote a location and a direction in Unity is the Ray.
The Ray consists of two Vector3 data points. The first Vector3 is the source position the ray is taken from and the second Vector3 is the direction of the target.

When a direction Vector3 is Normalized it keeps it’s direction but it’s length (how far away one object is from another) is set to a point between 0 and 1.  In Unity they round down to 0 if the objects are very close to each other (anything under about 0.04f of a unit) anything above that gets Normalized up to 1.

As an example we can simplify a bit by limiting ourselves to a Vector2.

A Vector2 can also be either a point or a direction depending on what you want to use it for.
If it’s (3, 0) then it could be either a point at x=3, y=0, or a direction along the x axis (one dimension) with a length of 3 and a slope of 0.
If you Normalize() that example the Vector2 becomes (1, 0). It will have a length of 1 but still be pointing in the x direction.
If you add the y value (dimension) into the picture where x=3, y=3 the Normalized value becomes (0.7, 0.7). So without going into the maths of why … you can see that the axis/dimensions impact on each other to define the Normalized direction.

We can extrapolate this into three dimensions without too much difficulty but I’m not going to describe that here as it’s not that necessary to understand. We only need to grasp what this means and what sort of use you can make of it in a Unity project.

For Example…

This is a simple use case of why you might want to use Normalize().

(Note that there is also a Normalized() function where the current vector is left unchanged and a new normalized vector is returned).

I’ve created an example project where the relationship between two objects (a Cube and a Sphere) will give us a direction (using Normalize()).  The direction is applied to a transform.Translate function on a third object (a Cylinder) which now moves in the given direction.

In this script below attached to our Green Cube (the unchanging point of origin – 0, 0, 0) we define the Pink Sphere as the target.  In the script we get the difference between the position of the sphere and the Cube and Normalize() it to make a direction. It doesn’t matter how far the Sphere is from the Cube the direction stays the same.

Also to extend the example I’ve added a Ray with the same origin as the Cube (0, 0, 0) that will always point to the Sphere.  This shows that the Normalized Vector3 is the same as the direction of the Ray pointing to the Sphere.

Normalizing Direction

The public Vector3 lineDirection is the difference between the position of the Cube and the Sphere. This is the variable we will pass to the Cylinder to move it in the required direction.

``````using UnityEngine;
using UnityEngine.UI;
public class HowToNormalizeDirection : MonoBehaviour {
public Vector3 lineDirection;
public GameObject target;
public Text vector_text;
public Text norm_text;
public Text ray_direction;
public Ray whatsTheRay;
// Use this for initialization
void Start () {
lineDirection = new Vector3();
whatsTheRay = new Ray();
}
// Update is called once per frame
void Update () {
lineDirection = target.transform.position - transform.position;
vector_text.text = "Vector3 target.transform.position :" + lineDirection;
lineDirection.Normalize();
norm_text.text = "Vector3 Normalized() :" + lineDirection;
whatsTheRay = new Ray(transform.position, target.transform.position);
ray_direction.text = "Ray : " + whatsTheRay.ToString();
}
}``````

Moving the Capsule in the Same Direction

In this script below attached to the Cylinder we get the direction from the lineDirection variable above but we could also have used the inbuilt Ray.direction function to return the same result.

``````using UnityEngine;
public class MoveCapsule : MonoBehaviour {
public Vector3 direction;
public float speed;
// Use this for initialization
void Start () {
direction = Vector3.zero;
speed = 0.50f;
}
// Update is called once per frame
void Update () {
var script = GameObject.FindWithTag("Cube").GetComponent();
direction = script.lineDirection;
//direction = script.whatsTheRay.direction;
transform.Translate(direction * speed * Time.deltaTime);
}
} ``````

In the Video below you can see this demonstrated. The position of the Pink Sphere is being manually manipulated using the Transform on the right. The text areas expose the vector3 values being accessed by the objects and scripts.

So what’s going on in this video amateur hour?

The three lines of text at the top of the game scene represent:

1. The Vector3 Position of the Pink Sphere.

2. The Vector3 Normalized  direction which is the relationship between the position of the Green Cube (0, 0, 0) and the Pink Sphere (x, y, z).

3. The uses of Vector3 in the Ray.  First the position of the origin and then the Direction of the Ray which is exactly analogous to the Normalized Vector3 in point 2 above.

The uses for something like this could extend to a weapon aiming system, a custom controller or be passed into a path finding routine. This is not the only option of course there are other built in methods like transform.LookAt(target) available which may accomplish your programming goal.

During the research for this post I found the following links helpful.

https://docs.unity3d.com/ScriptReference/Vector3.Normalize.html
https://docs.unity3d.com/ScriptReference/Vector3-normalized.html (which is a different but related function)
https://www.dummies.com/education/math/calculus/finding-the-unit-vector-of-a-vector/ (for why you really don’t want to know about the math or do it by hand)
https://www.mathsisfun.com/algebra/vector-unit.html (best for simple vector explanation)
https://docs.unity3d.com/ScriptReference/Ray.html
https://docs.unity3d.com/ScriptReference/Ray-ctor.html

# Animating the Running Dog with Unity and GIMP

I finally got the game I started in November into some semblance of how I wanted it to look.  The running dog animation anyway.  Still playing with different backgrounds but this one is sure “fun”.

It took a long time to get all the dog actions done drawing each one by hand and getting a lot of unsatisfactory results.  The animation is all “flip-book” style with each frame a different drawing.  There were between 70 to 80 pictures for the entire set.

The art was done in gimp with the help from some nice veterinarian manuals on the dog gait.

I mocked up a few transitions from an opening scene to a nice zoom down to playing position.

Then moved between a sedate walk to a running gallop and a little jump.  She looks like she’s really flying now!

During this time I also had a big problem with corrupted a scene after playing in the Animator window.  Big tip and future post – do not restart Unity if it crashes without taking a copy of your temp directory first. It took me about two weeks to rebuild everything but more on that later.

# The Five Games in Ten Weeks Challenge!

Some months back I went to a local presentation by the Unity champions at The Arcade (a collaborative workspace specifically for game developers and creatives) in Melbourne.  It was one of those “learn about others and gain insight into one’s self” moments.  One thing I picked up from one of the presenters from Hipster Whale (makers of Crossy Road) was that when they were developing a new game they tried to keep the proof of concept to a two week period.  Some time later with this in mind I presented to myself the “Five Games in Ten Weeks Challenge!” to see if I could really push out five different games in ten weeks.

Five Games in Ten Weeks

# New Game! Peace Run

Hi Zulu here  – We started work on a new game this week called Peace Run.  I wanted to do a continuous runner and really liked the idea of having a line drawing animation that looks like the player character “grows” out of the line.  The runners will be animal silhouettes like the dog shown here.

Doing the frame by frame animation has been really fun but it took a lot of trial an error to get to this point – which as you can tell isn’t perfect yet.

All the artwork was done in GIMP 2 and the game design is in Unity3d.  We used a simple animation script to play the start of the walk sequence.  I can’t wait to get this puppy into a run and a full sprint.