Alright. Now, we are at the point where we are going to dig deep into actually understanding how to write all this code that we have been learning thus far. We are at the stage that I call the ‘fingers on the fret board’ part of learning. That is a guitar reference, and I use it because it is an example of when you are first trying to learn something, you start with the most basic fundamentals that aren't always really that interesting to learn, kind of seem unnecessarily difficult, and are a bit of a struggle. The biggest struggle, usually, is at the beginning. I use this reference also because I am reminded of when I first learned how to play guitar. It was my first instrument I learned how to play. I was ten years old, and I distinctly remember trying to hold this guitar properly and get my little fingers onto the fret board, and back then thinking, "This is impossible." I thought, "How ridiculous, the effort required, to get only a single, solitary note." I had to press really hard and contort my hand in such an awkward and unintuitive way. It is really easy at these awkward and unintuitive early stages of learning something new, to have thoughts like, "Maybe this just isn't for me." "Maybe me and my little lady fingers just aren't built for guitar playing." Or, in this case, "Maybe my brain just isn't built to understand code." It is easy to think that way, but I came to find that if you don't quit, just as I didn't quit on learning to play guitar, you will probably come to find that, even just with cursory interest, bedogged persistence...
Persistence is always the most important factor in learning something new, I have come to find. Eventually, you will find that your brain just can't do anything but take in all that information, process it in the background subconsciously, until one day you will find yourself holding the guitar right and getting out notes with ease, or finding these hieroglyphic looking symbols called code starting to make sense. That is a pattern I have come to find in life, when learning something new, if you stick with it, eventually you'll look back and wonder what the big deal was to begin with. You barely even recall how it is to hold the guitar wrong. You can't help but hold it right, it just becomes second nature. The same thing with learning to read and write code. That is a life lesson I have used time and again to push through perceived obstacles, reminding myself of this pattern. Everyone goes through it, it is a normal part of learning. I am not going to candy coat it, we are at the part where I am not going to lie to you, things might seem at times a bit dry. You may not totally see how learning this one little, specific thing, that produces one little, specific result will translate into empowering you to be able to create really cool things. Trust me, it all relates, and just like putting your fingers on a fret board, it all eventually leads to the greater reward of you being able to get out your creative ideas.
Alright, on to understand C# at its fundamental basis, as well as its usage within Unity. This is the first thing you should know in regards to coding with Unity within C#. There is a distinction there. There is a language, C#, just as it is, how it works irrespective of Unity wrapping itself around it. There is the implementation of it within Unity. The particular ways that Unity emphasizes certain practices and de-emphasizes others. You will come to find that Unity constrains your programming choices. Not in principle, but in practice. Which, ultimately, should make things easier for you, but can be awkward at first. For example, we will be going into Object-Oriented Programming with C#, because C# is all about OOP… Object-Oriented Programming for short. The Unity API is built on these OOP principles, but by coding through the API as your interface to this OOP code underneath, some of those OOP practices won't make as much sense to use the way you will come to learn them, when learning simply pure C#. You will come to know what I mean by this, it is sort of like a dual nature of C# with Unity. There is C# as its fundamental OOP foundation, and there is the implementation of it in Unity through the Unity API as its interface. A lot of buzz words and funny sounding lingo, but trust me, it is not that complicated. It is just you will have to come to understand C# and Unity a bit separately.
As we move along, I will be mentioning where and when the concept I am teaching you is a fundamental C# concept, or a Unity-specific implementation of it to help make it a little bit more clear what I am talking about. Anyway, don't worry about that, it is a little preface, maybe more for you experienced coders out there than you beginners. The first thing we will do to keep things simple, clean and stripped down, so you can really focus on what really matters, is we will put aside all that code that we wrote for a prototype for now, and instead make a test script that we can use to create code and see the result output in the console. That way, we can go through the Unity engine, but not get distracted by too many visuals coming at us. Instead, we want to really focus on the code in its simplicity and see the results output just in the text console window that we saw earlier. In the great tradition of programming tutorials, it wouldn't be a full program tutorial without a hello world script, so we will create that right now. You may have seen these before, it is just a demonstration of the simplest way to output a message on the screen. Hello world, because I guess we are pretending that we are generating a conscious machine here. I am sorry to disappoint, we are not doing anything that awesome and sophisticated here. In fact, I don't think anybody has done anything that awesome and sophisticated yet, not for a while.
Anyway, we are going to want to create a simple test script, and go to your assets as you have seen before, create C# script, we will just call it Test. Remember, in order to output to the Unity engine, we have to attach it to a game object. I could attach it to any game object here, but I am just going to make a new one, just to keep it clean, and so we can reference it. We will call that Test. Right now, right away I will drag it and drop it there onto my Test game object, just so it is working. We are going to want to open that up, and write a simple "Hello World." Let's just make it super simple. Get rid of everything we absolutely don't need to start off with. So there is just a little bit less clutter. We just need the using engine declaration, keep that at the top. You don't have to worry about it being a public class, so just delete that.
We do need it to derive from MonoBehaviour. We will go into that a lot later. We don't need an Update() method, so just delete that, and simply write this message in your Start() method. Save that. Go back to Unity, and remember it is going to output through the console, so there is our “You have been eaten” output that we had from previous. Remember to make sure to have clear on play selected, and these notifications also selected as I have here. Let's press the play button so we can see the output, and there we go. We have “Hello world” outputting to the Unity. As I said, don't worry about the visuals that are happening in the game, they are ultimately not important, just look at the console window. Let's look at this code.
It is about as stripped down and as simple of code that we can right now put in Unity. Let's break down this code in a very cursory way and look at it starting from the top, moving down. At the top we have the using declaration, where we are using UnityEngine. Using declarations at the top of your scripts are the way that you import pre-written classes of code for use within your current script. It makes that library code available within the script, if you so choose to use it. In this case, the script is importing a UnityEngine library of code, which is basically the entire Unity API, its entire code base, in order for you to access it and output back out to the Unity engine. For example, in this script, we make use of the Log() method right here that is found in the Debug class, as well as the Start() method, that also we inherit from the MonoBehaviour class.
I am not going to go into inheritance just yet, but just know that that's what this part means. The MonoBehaviour part is inheritance, and the Log() method comes from the Debug class, which we all eventually get from the UnityEngine reference here at the very top. Much more on this later, just a cursory look for now. What we will want to look at much more closely is the class definition we have here. We start with the class keyword which just tells the compiler that everything within this set of squiggly brackets, which are like the walls of our container, everything inside of that container that we labeled Test, is within this class. For now, think of classes in the simplest way possible, which is just a labeled container that keeps things logically separated in code, the same way that you would use your dresser drawer to presumably keep your clothes separated, if you are good about doing such things. Your clothes can be separated from each other, so you know what is contained where. Each drawer would be its own class, if you want to keep this analogy, and you can label those drawers if you are particularly fastidious about such things. Sock drawers, shirt drawer, et cetera.
The only member right now in our Test class is the Start() method definition, which is a different kind of sub-container. Method definitions are special kinds of containers that must exist in classes, and contain entire sequences of code or code blocks, if you prefer. You can see here, in this Start() method definition, we have the Log() method that takes whatever phrase, string technically, that we pass in in between the parenthesis that you see here. Somewhere, somehow, it outputs into Unity through our console. This is already quite a bit to wrap your head around if you are not familiar with programming, and we are only talking a few lines of code, but here we already have a multi-layered concept of containment, or encapsulation in coding speak, that is going on here. You have got the class container, the outer container, and within that you have another container, different kind of container, your Start() method, which within it, there is a call to another method. You even have this concept of method definitions, where you have a set of code within squiggly brackets, and method calls, which is actually calling that definition and using it.
You already have a lot to look at here, and it is probably difficult to get your head around right away. I am not expecting to, so stick with me and we will go slow, I promise. This will be our basic understanding of the way our code will be structured going forward. This will be our common structure. You will have a class container with some members. Right now, we are only looking at methods. In those method definitions, you will have entire code blocks that you intend to call later in your code, and it will execute in full. We can't keep looking at this zoomed out, birds eye view, and attempt to understand what is going on. So, we have to zoom in at some point on each bit of code. I think the best part to zoom in on right now would be to focus on these method definitions, as much of the code we will be writing will be within these method definitions. You can start off by understanding a method definition as a set of instructions, as I mentioned before. It is like when you buy office furniture, it all comes disassembled, you get a piece of paper with some written instructions, often poorly, as it were. This piece of paper is just the instructions. You have yet to actually use the instructions to put together the furniture.
When we are creating a method definition, we are creating this instruction set, which later needs to be used or executed. You execute those instructions elsewhere in your code by calling it by name, followed by the invocation parenthesis invoke like a wizard invokes magic, think of it that way. In this example, the Start() method definition calls the Log() method. The Start() method itself is called elsewhere, and the Log() method definition comes from elsewhere. This is all handled by Unity, a little bit too much to go into right now, but just understand that that the Start() method definition that we have here is being called somewhere, in the same way that the Log() method is being called in the Start() method definition. Actually, what I will do is, why not just make a really quick method definition from scratch and call it ourselves. Why don't we just make a little method that just outputs that message. Type void... We will talk about void later. MyMethod(), arbitrarily named, nothing in the parenthesis, and just put in the Debug.Log() message that we had before. Now, here in Start(), I will call MyMethod(). I need a new keyboard; I am so sorry. MyMethod() by name, just like that. Save that, and we will run it in a second. I have created my own method definition with a set of instructions. Actually, it is not a set, it has got exactly one instruction which is our call to the Debug.Log() method with our message in there, then we invoke it, we call it, within the Start() method.
Which, we then know, in turn gets called by Unity somewhere within that vortex when we create a Start() method definition. It just ends up piping into some unknown wormhole and ends up on the other side, in our Unity display, either through the console or in the game world. Right now, we will see it in the console. Save that, go back to Unity, press play and no change. It says "Hello World," so it works exactly the same way on the output, but hopefully that makes it a little bit more clear how a method definition is different from a method call. A really basic way of understanding method definitions and method calls. A lot more to be said about methods much later. Right now, I just want to give you a cursory understanding of how methods are defined and then later called.
Just so, in the next few videos, when we write all these instructions in our method definitions, you have some sense of what is going on with those methods and how it is being piped through the Unity engine. That will become a lot more fleshed out, a lot more clear, as we move along. Just remember that we write instructions in our method definitions, and we execute them by calling the methods by name. In the next set of videos, we will be writing those instructions and focusing on exactly how to do that. That will be the heartbeat of much of our coding in Unity. Alright, see you next set of videos.
Lesson 9 - C# Fundamentals and Hello World