Fmod Built-in Parameters

Here is a quick view at the parameters that Fmod offers us out of the box. The great thing about them is that you don’t need to explicitly send the values to the event instance, the Fmod engine takes care of this for us.

So let’s have a look at how the Fmod docs describe them and then I will go into details to see how they can be useful and how i use them myself:

  • Distance built-in parameters track the distance between the listener and the event instance in game distance units.

  • Distance (Normalized) built-in parameters track the distance between the listener and the event instance as a fraction of the difference between the event's minimum and maximum distance. This allows anything automated or triggered by a distance (normalized) parameter to respond to an event's minimum and maximum distance properties changing as your game is played.

  • Direction built-in parameters track which way the listener is facing relative to the event instance.

  • Elevation built-in parameters track whether the event instance is above or below the listener.

  • Event cone angle built-in parameters track which way the event instance is facing relative to the listener.

  • Event orientation built-in parameters track which way the event instance is facing relative to the way the listener is facing.

  • Speed built-in parameters track how quickly the event instance is moving relative to the listener.

Distance parameters

Distance is an obvious and clear one but I have three thoughts or tips anyway. Firstly, this is measured in game units, so make sure you know how much a unit “feels” in your project. It could be metres, inches or light-years, it all depends on the scale of the game.

Secondly, you may think this parameter is kind of useless since the spatializer already attenuates audio with distance but sometimes you want to change the audio in different ways as the distance increases. For example, you could have a lowpass filter, a compressor or other effects that change your event with distance. You could also have aural LODs, that is, audio sources that play different loops depending on how close you are to the source. So imagine a machine: if you are very close, the audio is very detailed and intricate but as you move away from it, we only play simpler layers. Once you are far away, you can only hear the machine humming faintly.

Thirdly, sometimes you don’t want to attenuate audio using the spatializer. In this case, you can add a distance parameter and automate the master fader based on the distance. This allows for far more intricate curves and also has an additional advantage: if you do this on a gain plugin instead of on the fader, you can save everything as a preset to use on all similar events. Don’t forget to turn off the distance attenuation on the spatializer though, or you would be attenuating twice!

Distance (Normalized) is a cool one. This parameter always goes from 0 to 1, where 0 represents the event’s min distance, while 1 is the max distance. So you can automate your event using distance like I explained above but with the additional advantage that if you need to change the min or max distance after the fact, you don’t need to tweak all your curves since they are already relative to those values.

Elevation

This one is useful if you want to change your event’s audio based on the vertical distance between source and listener. Values go from -90 to 90. Negative values mean the sound is below you, while positive ones indicate the sound is above you. Not sure why the values go from -90 to 90, since there are no angles involved, as far as I know.

This parameter can be useful to achieve some poor man’s vertical occlusion. If you have some sounds coming from a different floor in a building, you can use this to approximate some occlusion although it has obvious limitations.

Speed

This one, despite what the docs say, is now divided in two versions: relative and absolute. The first one is the same one the docs mention, the relative speed between the listener and source. As you may imagine, the absolute version ignores the listener and just measures the absolute source speed.

Is important to note that this would only work if the audio event is attached to a GameObject and moved using the physics engine. That is, it needs to have a rigid body in the case of Unity. If you move an object by code using the transform position or you move it with an animation, that would not work and the speed will always be 0. Remember that the same also applies for the built in doppler effect Fmod has.

Orientation parameters

These can be tricky to wrap your head around. They basically define the relative facings of the listener and audio source. We have three different parameters: Direction, Event Cone Angle and Event Orientation. Let’s try to understand the difference between them.

Direction takes into account where the listener faces, regardless of the orientation of the audio source . To see what direction really measures, let’s draw a line from our audio source to the listener (shown in green). Direction is the angle between this line and where the listener is facing (red arrow).

Is important to note that direction doesn't care about where the audio source is facing. It is measured in angles, so as you can see, ‘0’ means that the listener is looking directly at the source. Negative values indicate that the source is to the left of the listener, 90 being directly to the left. -90 is just the opposite, directly to the right. To represent the listener looking in the opposite direction we use 180 or -180, both mean the same thing.

Direction is useful to make things louder when the listener is facing them, particularly when an audio source emits audio in all directions. So, for example, a firecamp would not be louder from any particular direction, the only thing that would make it louder for a listener, apart from distance of course, is the way the listener is facing. From the same position, if you are looking directly at the fire, the sound would be louder than with your back to it.

Event Cone Angle is almost the reverse of Direction. We draw a line between audio source and listener (again in green). The event cone angle is the angle between this green line and where the audio source is facing.

Again, take into consideration that we don’t care about the angle the listener is facing here. Something important to keep in mind is that the event cone angle doesn’t differentiate between listeners being to the left or right of the source which is why the values go from 0 (listener is facing the source) to 180 (listener is looking in the opposite direction the source is). Thus, 90 would represent the source being to the side of the listener, no matter which side.

Event cone angle is usually used to make events louder when the source is facing them, while making them quieter or more muffled when the source is not in front of them but to the side or behind. This could initially sound similar, maybe too similar to how we use direction. It was to me. The key to see the difference is that here we don’t care about the listener orientation, only where the audio source is facing. So let’s say our audio source is a person talking. Definitely the sound changes as you move around the person since the human voice is somewhat directional, especially the higher frequencies. Being in front of the person would be the loudest, with an angle of 0, while being behind them would be the quietest, with an angle of 180.

Event Orientation is finally the last parameter we can use. This one takes into account the angle between where both the source and listener are facing. This may sound like a useful thing but it really isn’t if you think about it. Let’s have a look:

As you can see, here there is no green line. That means that we don’t care about the relative positions of the source and listener, we just care about where they are facing, relative to each other. If you look at the two 180 examples, you will see that two very different situations (opposites, actually) share the same value which may feel odd.

This is why this parameter is not not used very much. I have never found a situation to use it myself.

Orientation TLDR: Use direction to describe how the listener orientation angle to the source changes the audio. Makes sense with non-directional audio sources (like a fire camp) and directional listeners (like human ears). On the other hand, use event cone angle to describe how the audio source orientation angle to the listener affects the audio. Useful for directional audio sources, like the human voice. Of course, if you have a directional audio source AND a directional listener, you should use a combination of both parameters. On the other hand, event orientation can be ignored for most situations.

5 Tips to Improve in Game Audio

Here are some thoughts I had about working in game audio.

Finding another way

Is not unusual for audio to not have as many resources as we would like. The reality is that our discipline is not appreciated in the same way fancy graphics or cool social features are. But this doesn’t mean we can just do mediocre work. Bad audio is noticeable while good audio is often invisible but realy enhances the player experience.

Finding another way means that, as a sound designer, you must work within the contrains you have to make things work and this usually means making compromises with quality, level of detail and performance. So maybe you can’t realy do things the way you initially planned but you must be resiliant enough to go around the obstacles and deliver something great anyway.

Take time to experiment

Audio has personality, it has a spirit. Sounds connects us to nature in an instictive way, they remind us to animals and weather. When creating audio for a machine, a creature, UI or an environment, we are tasked with giving them a personality, a certain flavour. For this, it can be very helpful to think about what you want to convey, what is the function of this thing in the story and in the world.

Sometimes that’s not enough and you just need to try crazy things, random stuff and see what sticks. I have created some great sounds like this but this certainly means you need to be willing to experiment freely which is not always possible when you need to meet deadlines. So remember to take time to stop and smell the roses, even aimlessly. You will get to results that can’t be achieved any other way.

Use limitations to boost creativity

Don’t see limitations as an obstacle, see them as a way to thrive. Less is more, sure, but is deeper than that. When you are limited to, say a single synth or instrument or just a few tracks or voices you are really forced to learn the only resources that you have deeply and get a knowledge ans mastery that you would never get if you have an arsenal of dozens of plusings to choose from.

Keep in mind the big picture

Is easy to over focus on what you need to do each day. You make sounds and implement them following a plan like ticking boxes. This happens usually when you base your work on lists, spreadsheets or jira tickets. It seems like as long as you tick boxes and cross tasks, you are progressing. This is needed, sure, but never forget that that doesn’t mater at all if the overall result is not working.

Always remember, the final user and their experience. At the end of the day, nobody cares about how you made that sound, how that bit of code is brilliant or the fact that you are knocking down tickets. Take a step back and play as a naive player, see what works and what doesn’t.

Be in flux with information

Things are going to be changing and fast. Features come and go, they are transformed and expanded. It can be tough to keep track of all of this, particularly when audio is usually left out of these decisions. Setting good comunications and expectations with the team is important but also remember that game development moves fast and you can’t possibly know every single thing.

You need to find the proper bandwith of information for each phase of development and keep on top of things but never compromising the actual work you need to do. For me, is helpful to remember that things must be flexible, that nothing is set in stone.

Introduction to the FMOD API

These are some notes and pointers about using the FMOD API, particularly if you (like me) don’t have a lot of previous programming experence. I won’t tell you anything that is not already in the official documentation but take this a condensed reference to use when coding or just to get familiar with the API.

Getting started

You can find the official documentation on the FMOD website. In case you don’t know, API stands for Application Programming Interface and is pretty much a bridge between two different computer environments like two different pieces of software. In this case, the FMOD API serves as the bridge between a game engine like Unity which scripts are written in C# and the FMOD engine itself.

The FMOD API can speak C, C#, C++ & JavaScript although not all functions are available in all languages. I will give C# and Unity examples here but these can be easily translated into other languages and engines.

Do you even need to use the API?

It depends. Out of the box, FMOD can be used on Unity or Unreal without much code work. You will be able to load banks and play audio events with just the components that come with the plugin but as soon as you need to do more complex things, you will probably need to use the API, at least in a few areas.

emitter.png

Studio vs Core API

Before diving in, you will see that FMOD differentiates between Studio & Core API. Most likely, you will just use the Studio API since it talks to Fmod Studio making things much easier for us sound designers.

The Core API, on the other hand, is completely standalone, allowing to integrate the fmod engine in a game without even using Fmod Studio. This is aimed for more bespoke integrations and deeper functionality that in most cases is not really needed but it is good to know it is there as an option.

So for now on, I will focus on the Studio API since is the one I’ve used myself.

Studio API Structure

On a high level, the studio API uses a series of concepts and classes that we should famliarize ourselves with. The main “brain” is the class RuntimeManager which will create and initialize an Studio::System instance which, in turn, will be the class we will use to call engine wide functions like setting global parameters.

By default, you don’t need to do anything for this to work as the fmod implementation in Unity or Unreal will get his ready for you. Studio::Bank can be then used to operate on the different banks themselves while Studio::Bus and Studio::VCA will allow you to get and set data on the mixer elements.

The concept of events in FMOD Studio is mapped to an Studio::EventDescription so if you want to do anything related to individual events that is what you will use. But keep in mind that you can have many instances of an event, so the API allow us to affect each of these through Studio::EventInstance. To be able to do this, you will need to cache a reference to each instance you play if you want to have full control of them. Usually, we don’t need to cache one-shots instances since we don’t need to affect them once played.

Also, remember that snapshots, when played, are also considered event instances so you can have all the same functionality for them and I would personally recommend creating a dedicated snapshot manager to keep track of them.

With that basic structure out of the way, let’s see what the API offers.

Studio API: Types

FMOD defines a bunch of types which will be very useful to get information about the audio engine. This are just a few commonly used types but there are many more.

Function Example Description Parameter Description FMOD.Studio.PARAMETER_DESCRIPTION Contains all the information in a parameter, including name min and max values, etc.. Loading State FMOD.Studio.LOADING_STATE Useful to know the loading state of different things, like banks and make sure we only use them when thay are loaded. Playback State FMOD.Studio.PLAYBACK_STATE; This one is SUPER useful so you can check if an event is playing, stopped, sustaining, etc... 3D Atrributes FMOD.ATTRIBUTES_3D The 3D position of an event or listener. This is a struct of simple vectors so you may need to convert it to something more usable like a Vector3.


Studio API: System

These calls allow you to talk to fmod in a general way, that would affect the whole fmod audio engine. Here are some of the most useful functions with some examples:

Function Example Description
Load Bank FMODUnity.RuntimeManager.LoadBank(bank, bool); Where "bank" is simply a string with the bank name. Make the bool true if you want to pre-load the sample data. I'm not sure why this can be done with just the RuntimeManager without using StudioSystem.
Unload Bank FMODUnity.RuntimeManager.UnloadBank(bank);
Get Bank FMODUnity.RuntimeManager.StudioSystem.getBank(path, out bank); Use this to grab a reference to a specific bank. "path" is the bank name (a string) and you will get a "Bank" struct type.
Get Bank Count FMODUnity.RuntimeManager.StudioSystem.getBankCount(out int count); Get the number of banks already loaded.
Get Bank List FMODUnity.RuntimeManager.StudioSystem.getBankList(out Bank[] array); Get an array of the type "Bank". Use with the one above if you need to get a reference to all loaded banks.
Get Listener Attributes FMODUnity.RuntimeManager.StudioSystem.getListenerAttributes(int listener, out FMOD.ATTRIBUTES_3D attributes, out FMOD.VECTOR attenuationposition); Use this to get a reference to the listener position which can be useful to calculate distances to emitters. The default listener is in index 0. There is also a set version of this function..
Get a Bus Reference FMODUnity.RuntimeManager.StudioSystem.getBus(path, out Bus bus); Get a bus reference so you can then use it. "path" is the bus string name. "bus:/" will always be the name of the master bus. You can also find a similar function for VCAs.
Get an event description FMODUnity.RuntimeManager.StudioSystem.getEvent(path, out EventDescription _event); This is very handy if you want to do something with an specific event. As usual, "path" is the string name.
Set a global parameter FMODUnity.RuntimeManager.StudioSystem.setParameterByName(name, value, ignoreseekspeed); Sets a value to a global parameter where "name" is a tring with the name of the parameter, "value" is a float and "ignoreseekspeed" is a bool.

Studio API: Bank

We won’t be able to do much until we have our banks loaded. Keep in mind that the master bank always needs to be loaded as this contains mixer information like buses, vcas or snapshots. Other than that, all other banks can be loaded one by one as needed. I talked about how to get a reference to a particular bank above, let’s now see what you can do with that reference:

Function Example Description
Get loading state Studio.Bank.getLoadingState(out LOADING_STATE state); We can check if a bank has finished loading before doing anything with it.
Load Sample data Studio.Bank.loadSampleData(); This will load all the audio files themselves into memory before any audio is played. Use this if the events are very time sensitive or you want to trade CPU for memory. There is also an unload method.
Unload bank Studio.Bank.unload(); Use this if you are sure you don't need the events contained on this bank anymore so we can save some memory.
Get the event count Studio.Bank.getEventCount(out int count); Check how many events the bank has.
Get event list Studio.Bank.getEventList(out EventDescription[] array); Use with the above method to get an arrray of event descriptions in case you then want to do something with them.

Studio API: EventDescription

You can find here all functions related to each specific event set in FMOD Studio. Before you use this, remember that you need to grab a reference to the event description using the method described in the section above so you can only do this once the bank containing the event is fully loaded. Once you have it, you can get some very usefu information from it. Here are some examples:

Function Example Description
Create Instance FMOD.Studio.EventDescription.createInstance(out EventInstance instance); Use this to create an instance which you must do before you play the event. It can be a good idea to cache the instance for use later.
Load Sample Data FMOD.Studio.EventDescription.loadSampleData(); This is very handy if you want to load the sample data for an event before you play it. Particularly useful for time sensitive events.
Is 3D FMOD.Studio.EventDescription.is3D(out bool is3D); Check if the event is 3D whcih would be determined by the event having an spatializer. Nice one if you create your own emitter or player.
Is Valid FMOD.Studio.EventDescription.isValid(); Use this one to make sure the event is not null and can be used.
Is Snapshot FMOD.Studio.EventDescription.isSnapshot(out bool snaphot); Check if a particular description is a snaphot.

Studio API: EventInstance

As mentioned before, we need to create an event instance in order to be able to play it or just do anything with them. Once this is done, we can have full control of the instance. Here are some useful methods:

Function Example Description
Play Instance FMOD.Studio.EventInstance.start(); Just play the instance. Basically, this will start the timeline, as set in fmod studio.
Stop Instance FMOD.Studio.EventInstance.stop(FMOD.Studio.STOP_MODE); Stops an instance. As you can see, we need to pass a stop mode which will determine if we respect any fades set in studio.
Release Instance FMOD.Studio.EventInstance.release(); This will tell the fmod engine that this instance can be deleted from memory. Use this after stopping an instance if you don't need it anymore. Important to prevent memory leaks.
Get playback state FMOD.Studio.EventInstance.getPlaybackState(out FMOD.Studio.PLAYBACK_STATE state) Use this to know the current state of the instance. Very useful if we want to check if the instance is playing before trying to stop it.
Set 3D Attributes FMOD.Studio.EventInstance.set3DAttributes(RuntimeUtils.To3DAttributes(position)); Sets the instance to a particular 3D position. Used to play audio in some specific place.
Attach to game object RuntimeManager.AttachInstanceToGameObject(instance, gameObject.transform, rigidBody); Use this for 3D events if, instead of playing in an specific place, you want to attach the sound to a game object.

Studio API: Bus & VCA

We can interact with the game’s mix by getting and setting values on buses and vcas. Check the system section to see how we can get a reference of a particular bus or vca but basically, we would need to know its name (as it was names in FMOD studio) as a string value so it could be a good idea to keep a reference of these somewhere in your code.

Let’s see a few examples of things we can do with buses and vcas:

Function Example Description
Set Bus volume Studio.Bus.setVolume(float volume); Sets a particular volume for this bus. There is also a get method.
Stop all events Studio.Bus.stopAllEvents(STOP_MODE mode); Stops all the events within a bus. Useful if you want to make sure all audio within a particular bus stops when unloading a level, for example. Notice that we need to pass the stop mode we wish to use.
Pause all events Studio.Bus.setPaused(bool pause); This will pause or unpause all the events contained in a bus. Use this for pause menus, for example.
Set VCA volume Studio.VCA.setVolume(float volume); Set volume on a VCA. Nice for the audio level settings.

In conclusion

I think if you understand how all the above work, that would be a very good start. Check out the FMOD reference docs for many useful examples and dont’ hesitate to drop me a line if you have any questions, I know some of this can be obscure until you use it for a while.

Brief Source Control guide for Audio Peeps

Here is a summary of ideas and concepts about Source Control or Version Control that I wished I knew when I starting out in game audio since they can get a bif confusing.

What is Source Control?

Basically, It is a system used within software development to share and keep track of code and other assets. Since many people will have access to the same files, you can see how this can create conflicts if two people try to change the same thing at the same time. Source Control has features and workflows to allow people to safely work without conflicting with each other.

It also allows you to work with different versions of the same application which share some parts of the code. At the same time, in functions as an advanced backup because all the work is both locally on every developer computer and on a server somewhere. Because of this, is easy to go back to a previous version if needed, like if something breaks, for example.

So imagine something like Google Drive or Dropbox but far more advanced so multiple users can seamlessly work at the same time and with different partial collections of files from a common pool in the cloud.

In summary, Source Control is a fancy way of sharing files between people in a way that allows for multiple versions and conflicts can be minimized and/or resolved when they arrive.

Git

This is one of the most popular pieces of software to do Source Control and you will probably see it all around. Since it was developed by Linus Torvalds (yeah the guy who is the reason Linux is called that way), it is a free and open source so anyone can use it.

As far as I can see, Git was 87.2% of Source Control software in 2018 so it is clearly the King.

What can be confusing at first, is that Git, more than an application itself, is a system or protocol. Git can be used on the terminal but more usually people use a Client, which is a dedicated App with a GUI (Graphical User Interface) so it is easier to use.

Fundamentally, you can use Git purely locally but usually it is hosted online so many people can access the same repository. So you need some server somewhere to do this.

In conclusion, Git seems to be the most used Source Control software and it is really a protocol that can be used by different clients and using different online services for hosting. Let’s see these:

Git Hosting & Clients

GitHub: This is a company owned by Microsoft which offers free online hosting for Git repositories. Many important open soruce projects are on Github, like Bitcoin. For commercial and more complex projects, Github also have paid options.

GitHub Desktop: This is a client, a software with a GUI that uses the Git protocol and can be used with Github hosting or really any other Git hosting (Even local).

GitLab: This is another popular online hosting service for Git projects.

Bitbucket: This is yet another online hosting service for Git owned by Atlassian, who also owns Jira (a task management) and Confluence (wikis) which are also popular in the game development industry.

Sourcetree: This is a popular client with a GUI to work with Git repositories and it is also owned by Atlassian.

Fork: Yet another client to use Git with.

TortoiseGit: One more Git client which integrates with the Windows File Explorer.

There are many, many more hosting services and clients but those above are some of the most popular.

Apache Subversion (SVN)

This is a completely different ecosystem and procol for source control. It uses similar concepts as Git but on other aspects is quite different. I’ve seen SVN used for larger files like art and audio within game development.

TortoiseSVN is a popular SVN client which integrates with the Windows File Explorer.

Perforce or P4

This another Source Control protocol software, quite popular in software and game development.

Terminology & Workflows

Now that we know a bit about the ecosystem, let’s see some of the concepts that Source Conctrol uses. This can be applied to any system but is mostly oriented towards Git.

repository is like a project that you create withing the Git system. So an app or a game will generally be one repository that is then shared by all the users.

When you want to get the repository in your local computer this is called Clonning. When doing this, you choose a folder in your drive and the Git client will download all the content. Once you do this, you have access to all the files, or to be precise to a version of all these files from the moment you did the clonning.

Although you are at first clonning the whole repository, while you work you are always dealing with branches. These are different versions of the software or game that are used by the team. Usually, there is a stable main branch called master or develop which functions as the principal branch where all other branches usually eventually point to.

After you clone the repo, if someone else updated it later, you will get “behind”. Source Control doesn’t usually work like Drive or Dropbox, where things are automatically updated. In contrast, you have update it manually. This may seem like a weakness but it is actually a strength. You need to have full control of when you are behind, ahead or just in sync with the server’s repository, depending on the situation.

Generally, if you are not working on anything at the moment, you want to be up to date with the master branch. For this, you switch to that branch (you check out the branch) and use the Pull action, which just pretty much checks if there is new stuff on the server and downloads it. In the case of SVN, this is action is called Update, which makes sense.

Keep in mind that when getting the latest version, you don’t get the whole thing again, just whatever is new or was changed, which makes things much faster. But what happens of you are the one who makes the changes? In this case, the simplest thing to do is to just send your changes to the server. In order to do this, git has two different steps which can be confusing. Before we go into those, we need to find whatever files we have changed and select them to make sure those are the changes that we want to upload. This part is important because usually there will be other local changes that we don’t really want to get into the server.

So after making sure that we have chosen the correct changes, we need to do these two step which are usually done at once but is important that you know the difference between them. The first is a Commit. This is just saying to the repo, hey I want to change these files and here is a brief description of what this change does. Once you do a commit, you have updated your local version of the branch where you are working on, but the server (or your co-workers) still have no idea that this change has occurred. The next step is a Push and that’s just the action of uploading your changes to the server for everyone to see.

As you can see, in the heart of this Commit and Push workflow is the isea of a Change, that is, the files that you have modified in respect to the server version that sits in the repo. Sometimes, you will make unintended changes which will break things. Since you are working with Source Control, you can always revert these changes, which will change the file back to its original state, which should be the same that exists in the server so no harm done.

Something else that it is important to know: You don’t usually work directly on the master or develop branch. This branch is usually reserved for an estable version of the game or software so people shouldn’t directly push things to it. That’s why we use branches. You would usually do your work in a branch you create, check that all works as intended and then push your changes to a server version of your own branch. Once that is done, you will create a Pull Request, from your branch to the estable one and usually someone with more seniority will check that all looks good and then accept the pull request. Once done, the result is sometimes called a Merge, since your branch is merging into the master branch.

And that’s all I have, it was quite a lot at once if you are new to this but I hope this works as an introduction from which you can expand as you get more and more into game development.

Learning C# Notes - Part IV: Methods

Here are my notes on eveyrthing related to methods.

Methods Basics

  • We can think of methods as the different actions that our classes can perform so they are the basic building blocks that determine how a class behaves.

  • Sometimes they are called ‘Functions’.

  • We first define a method using paretheses () after the name. Method names usually start with a capital letter.

  • After defining the method, we can call it from somewhere else.

  • See an example below. We first define a method and then it is called from some other method definition.

class Program { void FirstMethod() { // code to be executed } void OtherMethod() { //Some More code FirstMethod(); } }

Return Types & Passing Parameters

  • Methods can return a variable after they run, which needs to be specified when we define the method.

  • If a method returns no value, it will be of type void.

  • While return types are like outputs, we can also input information into a method. These inputs are called parameters.

  • For a method to take parameters, we must define them when we define the method.

  • A method can take multiple parameters.

  • We can give parameters a default value by using the equals sign when defining the method.

  • The ‘params’ keyword can also be used to make a parameter optional.

    • To be precise, it allows you to pass any amount of elements in an argument's array and if you pass 0 elements this is in practice like making the argument optional.

    • The params keyword can only be used once per method and must be the last argument.

int SumNumbers(int num1, int num2) { return num1 + num2; } void MyMethod(string country = "Norway") { Console.WriteLine(country); }

Method Overloading

  • Multiple methods can have the same name and vary in how many parameters they take and even their return types.

  • This is useful when you need a method that can perform generally the same function but using different types of information.

  • We just define and call them as normal using the same method name.

  • See the example below. Both methods will just sum numbers but they can take different type of variables as values.

int SumNumbers(int num1, int num2) { return num1 + num2; } float SumNumbers(float num1, float num2) { return num1 + num2; }

Calling Method from other classes & Static Methods

  • When working in Unity with C#, most of the time, each class lives in its own script file.

  • Is very common for a class to call another class’ method.

  • This is usually done by typing the name of the class followed by a full stop and then the name of the method, ending in paretheses.

  • If we want to call a method within a class without instatiating that said class, a possible solution could be to make the method static when defining it.

Unity Methods

  • Unity includes some important methods that we can use on Monobehaviour type scripts.

  • Awake() is the first method called and it should usually be used for initializing things. Is only called once.

  • Start() is also called once after Awake() but inly if the script component is enabled.

  • Update() is called on every frame that the script component is active.

  • LateUpdate() is called every frame but only after everything on Update() has finished executing.

  • FixedUpdate() is the same as above but it has the frequency of the physics system.

  • OnEnable() is called when the gameobject containing the script is enabled and becomes active.

  • OnDisable() is called when the gameobject containing the script is disabled or destroyed.