Today some notes about git tips and tricks, which I often use and regularly forget.
They're not very "pro", just a few things I personally happen to find useful.
Today some notes about git tips and tricks, which I often use and regularly forget.
They're not very "pro", just a few things I personally happen to find useful.
When debugging some Unity-related problem, there is often need of finding which game object in the scene does something. We can use transform.name (or gameObject.name), but there are often multiple objects in the scene with such name. The better solution would be to log full path in the scene graph (in a manner : objectsGrandParent/objectsParent/theObject).
I don't know of any built-in solution for that, here is the helper class I've created for that purpose.
It takes transform as a parameter, of course we can call it with gameObject.transform if necessary.
It can be used like this:
As a result, if we add the MyBehaviour script to MyObject object in hierarchy like this:
... and run our scene, the logs will show up:
As mentioned in part 1, Unity editor is very easily extensible by scripting.
It basically allows to do almost everything you could by clicking by a script. And programmers do not like clicking, if something can be automated.
In the following article, I'll show you some simple steps to achieve some simple results with Unity editor, beginning with the basics of creating an editor script, and focusing on selecting, inspecting and modifying objects in scene. The information below is, of course, available in the Unity documentation - my goal is to put it in one place, in a simple question-answer format.
In the future I'll provide more similar examples, maybe a bit more complex (so that one would show a few editor features/how-to's)
Create folder named Editor in Assets folder, create a file named SceneTools.cs and put this code inside:
It's veery basic. It simply adds a menu item called "Do something" to Unity's Tools menu (and creates Tools menu itself, if it hasn't been added before). When clicked, it shows "Showing this log" text in the Console view.
Menu looks like this:
If we want to add some function to Unity's menu, we have to use the MenuItem attribute, and the method has to be static.
Ok, let's extend our script. We can add another method below the first one. Remember to change the name in MenuItem annotation (the menu item name). You can add as many methods (and, therefore, items), as you like to your custom menu. Just remember to change the names (in both annotations and methods' names) This time it will log the selected object's name and print it to console (only if at least one object is selected).
And here is our result:
Without the check in if, the line below would throw NRE if no object was selected.
Another method (we select the first object named "Andrew"):
If there is no such object, nothing happens.
For this one and another, update your "using" directives:
Here you go (use cautiously!):
If there is no such object in the scene, nothing happens.
To be continued. I think next time I'll prepare one more complex script, doing some made-up task, using the techniques mentioned above (and adding more).
Meta-blogger note for today: I have to find some way to add line-numbering to the embedded code here, and to make it wrap automatically.
This time some simple things. Possibly obvious for programmers with some experience... But maybe not so obvious for everyone? Once again we're discussing C# 7.0 used with Unity.
When using a method with an out param, you don't have to declare it before.
Which means you can write this:
as this:
The script in the previous part included very limited and basic use of functions. They were not returning anything, and they were quite simple. I also wasn't using any lambdas (which in Python mean simple, anonymous functions defined in a specific way). So let's take a look at a little illustrative program, showing how to define and call a function in Python, how to pass a parameter to it and return a value, how to pass a function as a parameter and how to define and use a lambda (in our case, passed as a parameter).
Once again, some programming experience may be needed to understand what's going on - the code below is just some simple examples of basic language constructions. This time: functions and lambdas. Some details in the comments. In the further part (below), one more notion regarging lambdas. For now, it's much less practical than the code in the first part, but I wanted to simply show (and note for myself) some basic syntax and use cases. Still not object-oriented.
The result of this running this code looks as follows:
The code in Listing 1 shows use of lambda in Python. The last call in the main:
show_first_10_values(lambda arg: arg*arg))
is the call to a function, which takes another function as a param and calls it 10 times, with arguments from 1 to 10. I think that, although not very practical itself, it shows more-or-less how to use lambdas.
Meanwhile, there is a common example of using such lambdas in Python, which, although technically correct, doesn't make much sense:
First of all - this code works. It prints a number 6 in that case. But the problem is:
What's the point of using lambda here, if it's basically a function? The same code could look like this:
... or even like this (please note it's the same code, just one code indentation is ommited):
... and well, that's what functions are for, right?
Such practice, although quite common in various articles on lambdas in Python, seems to be criticized in the official Python style guide.
In the first example (Listing 1, show_first_10_values(lambda arg: arg*arg)), there is at least some reason of using a lambda: we need to pass some function as a parameter, and we want to define it ad hoc . Please note this:
show_first_10_values(lambda x: x*x)
is simply much shorter (and elegant) than this:
The next part: collections and data structures.
Here's some syntactic sugar I've discovered recently and I was quite impressed. Please note it requires C# 7.x (Unity 2019 and newer should be ok).
First, a little background:
A typical method in C# returns one value. Until recently, if you wanted to return two values, like an int and a float, you could either use out parameters, or define a helper struct. But there is other way!
Let's take a look on "old" methods first (if you want to see the new way, it' in 4-th point below).
The problem with out parameters is that returning value via them is a bit less readable than a normal return, and the problem with a helper struct is that is has to be defined. Let's see how it looks like, for reference; and then I'll show you a bit more elegant way.
Let's assume we have our method, getSomeData(), which we would like to return two values: integer age and floating point height.
The first 3 examples below are to show you some context, my "discovery" is in the 4-th point :)
The typical way, similar to references from C++: we can "return" our values by out parameters:
Problem with this? Well, it doesn't quite look like returning a value. It looks like calling a method with parameters.
We can return one value and get other one via out parameter:
The problem with this version is that either of parameters is returned in a different way. If both are equally important, it looks strange (if not deceptive).
We can define a helper struct and return it:
This version is very clean and readable when we define and call out method, but...
... before that it requires us to create a whole new structure, just for returning two values at once.
So it seems... We can just return two values at once!
Today - something different. You'll learn Python (3) in 5 minutes, no need to thank... Ok, not exactly. But... Sort of. You know, when you have a little bit of experience and not much time, there is better way of learning some things (like programming languages), instead of tutorials and books. It's to take a look at the thing in action: in case of a programming language, it would be a short program, using some basic features of the language. The additionary benefit is that you can make it solve some problem you have.
Please mind this note should be quite helpful, if you already know some programming languages, but not Python in particular. If you are a beginner in programming, maybe you can use it as a simple "practical" reference, but you may have problems understanding what going on - I won't elaborate on all things (of course, if you have questions, please do comment).
Ok, so what was that problem in my case?
Well, I had been testing some feature of my Android game - to be precise, the notifications' logic. Some time after event A the app was supposed to show a notification, but only a limited number of times and in specific conditions (details are not important here). So at first I've opened Notepad and started to write things like:
...based on my app's behaviour and logcat.
After working with that for a day or so, I've realized that:
1) I have notes in 3 different editors open at the same time
2) I've been taking a note with a timestamp about 2 times a minute for a day (I check time, I write it down, I write the note, lot of work).
3) I can make things a bit easier...
And by 3) I mean:
I can write a simple script, which simply takes the input by user (followed with [ENTER]) and writes every line (with timestamp) to a file. And then if the user types r [enter] (r), it shows the notes so far. This way: everything is in one editor (which is my script), stored safely in one file (which fixes issue 1) ); and I don't have to manually check and write down the time (issue 2, and - inherently - issue 3).
And here is the script, which by the way is one of the programs I've mentioned in the beginning: it uses functions, flow control (loops, ifs), basic data structures, file I/O... Basically a first few lessons in every Python tutorial ;). Nothing advanced, nothing object-oriented for now. We don't need that for now... Maybe in the future.
I won't elaborate on the code - I think the Python syntax is very clean and self-explanatory, and I've commented it quite extensively. I think the most cryptic fragment is the if __name__ == "__main__": statement: it's simply the way you should call the main method in Python. You could just write main() in the last line; but when such script is imported as a module, it would be executed automatically (which most probably is not the desired effect). In our case it doesn't really matter (I would't advice importing this as a module ;) ), but let's follow the tradition.
The code is on github here - the linked version may be a bit different, because using it day-to-day, I'll probably tweak something in the future. Maybe I'll update this post too.
Next time I'll elaborate more about functions (and lambda functions). The next lessons will also be more descriptive about basic things.
Meta-notes for today: if you want such nice, monospace, syntax-colored code in Blogger, you can simply copy the contents of a file opened in VS Code (which makes a very nice Python IDE, BTW, with some plugins applied). It works out-of-the-box only for the files with syntax highlighting, so if you just create a new file and type some text, it won't. But in that case, you can use Ctrl+Shift+P -> type Copy -> choose Copy with syntax highlighting.
In the last part we've shown how to create and use a class in Python. Today we're going to talk about inheritance: wchich means cre...