I am having trouble finding where OnUserInput() is defined. WM2000 seems to have 6 scripts, main to sub folders. I’m not even sure I know exactly what I am not understanding.
What is looking for OnUserInput(); What is calling this method?
I had this same question, it seems like Ben has hidden a lot of the workings of the terminal so we don’t worry about it.
There’s a function in Terminal.cs called “NotifyCommandHandlers”. It seems like it loops through all the game objects looking for one that has a method called “OnUserInput”. That’s all I have figured out so far.
Yes, they’ve hidden some magic inside places like DisplayBuffer.cs and InputBuffer.cs… You’re on the right track, Clay… once NotifyEventHandlers finds your OnUserInput it hands it the content of the input buffer.
So, OnUserInput is defined by you, the student, in Hacker.cs as a pedantic answer. But where it get’s “input” from is the “buffer” running in memory alongside it. Technically, Terminal.cs does it with it’s NotifyEventHandlers method, but that is in-turn triggered by the “event” in the InputBuffer class…
Thanks Guys.
Hi,
what is the point of the course if there are hidden thinghs?
This is just a shot in the dark, but I would guess that Unity doesn’t have an easy way to perform simple string inputs. In other words, the details really aren’t hidden, but just a bit obscure…
And now that I look at it, NotifycommandHandlers (like JackDraak said) is doing a call-back to your “OnUserInput” method.
Hi Paul,
what is the point of the course if there are hidden thinghs?
The point of the course is to teach you in a style that will accommodate as many students as possible, all with different learning styles and abilities. There isn’t really anything hidden in this project. All of the files are there, in the same way if you were to install the Unity Standard Assets there are multiple scripts that do things for you, they are not hidden, but you do have to look for them.
This project gives you a framework of a game from the outset, some art assets, some sound effects, and to theme the keyboard entry to mimic an old style terminal some scripts have been written which you dont need to worry about, they just do their thing. This allows you to focus on the exercises in this section and on-board the information being given to you instead of thinking “Why are they teaching me how to make a keyboard sound effect play” on day one of your course. Additionally, there are a couple of techniques used in providing this mini project which are a little beyond the day-one-beginner, as I say, it’s a framework to get you started.
If you want to have a dig through and view what’s there you can, just expand the WM2000 GameObject and look at the child GameObjects and the components that they have to see how it all fits together. If you take a look at the script components you will see that there are some fields exposes such as how many vertical lines the screen will display, how many characters wide it will be, which font, the font size and so on. All this can be played with and changed to suit your needs, but for some students, they may find it more rewarding, at least initially to no worry about the framework example, and focus only on the course content and the information being presented to give them a bit of a grounding first.
All down to the individual really. If you are new to Unity and/or C#, I’d recommend working through this section first, then take a backup of your project once completed and then take a look at the WM2000 GameObjects and scripts and have a little play, see what little tweaks and changes you can make.
Hope this helps
Thank you for your response. I think that classes like Terminal, DisplayBuffer,
InputBuffer should be explained. Without the explanation, it’s a black box. I think it will be great if the instructor explains what the term System. Reflection means and why it is using in the code. It will also be great to know what the code below does.
public void NotifyCommandHandlers(string input)
{
var allGameObjects = FindObjectsOfType<MonoBehaviour>();
foreach (MonoBehaviour mb in allGameObjects)
{
var flags = BindingFlags.NonPublic | BindingFlags.Instance;
var targetMethod = mb.GetType().GetMethod("OnUserInput", flags);
if (targetMethod != null)
{
object[] parameters = new object[1];
parameters[0] = input;
targetMethod.Invoke(mb, parameters);
}
}
thank you
Hi Paul,
If you want a response from one of the instructors, specifically, your best bet is to post the question in the Q&A on Udemy, whilst they do drop in on the forums periodically, questions like these are not guaranteed to be responded to here.
Whilst I appreciate the black box concerns, you will find that the code being used in your example above is somewhat beyond the scope of the introduction level that most students would be comfortable with - hence why it isn’t really covered. That said, for those that either have more experience or just want to know perhaps a separate document could be added to the section on the course which provides and overview, definitely worth suggesting but probably best to do so on the Q&A.
Reflection can be used to get information relating to loaded assemblies (class libraries, such as UnityEngine.dll, or YourGame.dll etc) including the types (classes) that are contained within them, and to find specific methods and invoke them.
Here’s a bit of a walk through of the code you posted and what it’s doing…
The method NotifyCommandHandlers
receives the input from the player, this is passed via the input
parameter in the method signature.
Next, a search is performed in the scene to retrieve all of the objects which are of type MonoBehaviour, this is effectively scooping up a reference to every script in the scene.
The foreach
statement is used to then iterate through that collection of objects.
We are looking for a specific method, OnUserInput
, you add/use this method within Hacker.cs but it is also used within other scripts which belong to the WM2000 project (the parts you are now looking through).
Binding flags are effectively filters which help perform this search against the loaded assembly.
The if
statement is used to determine whether we found the specific OnUserInput
method on the current object we are working within, in our iteration.
If the targetMethod
is null
then we didn’t find OnUserInput
on the current object, so the next code block isn’t executed.
If however targetMethod
isn’t null, then we did find the method we were looking for, and now we can pass to it our player’s input.
First, we create an object array named parameters
, we initialise the array to a size of 1.
Next, we set the first element in that array to the value of input
.
Finally, we call Invoke
on the method, passing in a reference to the current object in the iteration and the parameters object array we just created.
This is like saying;
OnUserInput(input);
but we are able to use reflection to find all instances of that method name on any of the classes within the assembly, and pass the same input value to all of them.
In the case of Hackers.cs, you have added code to then validate the player input against a series of passwords etc. Other parts of the WM2000 project will receive this input and perform other tasks, such as playing the sound effect perhaps for the key press.
I hope the above helps you to better understand what that code is doing, and provides a very brief overview of reflection. It is very powerful, but is not really a beginner or introduction subject matter.
I would agree with you though that, for those who are curious, a brief over view in perhaps the form of a document linked to the resources for that specific section could well be beneficial.
Hope this helps
See also;
- Microsoft Docs : Reflection in the .Net Framework
- Microsoft Docs : BindingFlags Enum
- Forum User Guides : How to apply code formatting within your post
personally my thoughts, if I were starting out having to work through the WM200 object would have scared me off. Even a few months back after a good while at C# and unity, theres a few things tucked away that still took a bit or wrapping my head around.
in a good and practical way, imo this tends to lean on one of the encapsulation pillars, which will serve well down the learning journey, you dont have to know how someting does what it does, as long as it does what its supposed to do, which is something you will get used to down the road. and with that in mind, at this point in the course its a generalisation of coding, not too heavy, just a nice paced primer… then once we cut our teeth a bit we can go back and discect it and see what makes it tick
Thank you! very helpful
You’re very welcome Paul
I’m glad that I am not the only one wondering where they pulled this method from. I was thinking that it was part of some kind of library that we don’t see.
The way I understand it it looks like Terminal.cs looks across all game objects for “OnUserInput” and then Invokes a method based on that string name. Perhaps the reason for this is to ensure this works from all game objects regardless where which game object we put Hacker.cs script as a component into ???