Optional Variables - Unity Tips [2020.1+]

  Рет қаралды 19,758

aarthificial

aarthificial

Күн бұрын

Пікірлер: 102
@clonkex
@clonkex 3 жыл бұрын
This is the kind of thing that makes me love programming. You're not only programming a game, you're programming the tools to program the game.
@chadykarlitch
@chadykarlitch 2 жыл бұрын
100%
@FriedMonkey362
@FriedMonkey362 Жыл бұрын
I didn't even know u could do that in unity
@Sephta
@Sephta 3 жыл бұрын
These are real workable "tips and tricks" that I, and im sure plenty of other people, would love to see more of. If you're able to, please create more content like this!
@aarthificial
@aarthificial 3 жыл бұрын
I'll do my best!
@aarthificial
@aarthificial 3 жыл бұрын
@EDIT I've updated the gist to correctly support prefab overrides. I have a really exciting topic for my next devlog! Sadly, it will take some time to make so, in the meantime, I wanted to create something less ambitious. Thanks for watching!
@geekjoystick
@geekjoystick 3 жыл бұрын
Really nice to have small tutorials like that, and more generally giving an idea of how things work in your game. Personally it really helps me to better structure my own ideas and projects. Keep up the good work :)
@aarthificial
@aarthificial 3 жыл бұрын
Thanks, I'm happy to hear that!
@ariehuybregts9875
@ariehuybregts9875 3 жыл бұрын
This is such a useful function/struct that exists in a couple of scripting/markup langs I use that I've been wishing was in unity
@octsonandivorgias7007
@octsonandivorgias7007 3 жыл бұрын
Short, Simple, and Straightforward. This video deserves more views!
@WingedOriTV
@WingedOriTV 3 жыл бұрын
This Dude deserves more subscribers and views!
@_kett2164
@_kett2164 3 жыл бұрын
that is brilliant! I just finished a project in unity and this definitely would have come in handy I am hyped for the next devlog!
@early2000skid
@early2000skid 2 жыл бұрын
Very nifty struct :) I'm curious as to how you created an empty PropertyDrawer at 1:31 because not having to write the boiler plate for that would save so much time. Not sure whether that's an inbuilt Unity thing or a unique feature of your IDE. Looks I've got some research to do, great vid Aarth :)
@tiredko-hi-
@tiredko-hi- 3 жыл бұрын
I really like this solution. Easy to use, understand, and works perfect. Nice tip!
@Hoowwwww
@Hoowwwww 3 жыл бұрын
i don't use unity, but i love watching your videos, quality content!
@aarthificial
@aarthificial 3 жыл бұрын
Thank you 🖤
@chris.davidoff
@chris.davidoff 3 жыл бұрын
Found this from Unity's blog, and I'm stoked! I want to try benchmarking this to see the difference
@hazemsamy9058
@hazemsamy9058 3 жыл бұрын
That's a great tip! will definitely come in handy with my current project. These types of videos are so informative and straight to the point, would be amazing if you gave us more of these useful snippets. Also, can't wait for the upcoming devlog, you have a great game in the making. Best of luck and keep up the great work.
@aarthificial
@aarthificial 3 жыл бұрын
Thanks so much!
@RandomProduct
@RandomProduct 3 жыл бұрын
Just discovered this channel. These are incredibly useful, and you've got a smooth voice. I could see your stuff blowing up, my dude.
@RandomProduct
@RandomProduct 3 жыл бұрын
Also, after watching the pooling video, I gotta say your animations are so helpful in understanding these topics. Very well done!
@aarthificial
@aarthificial 3 жыл бұрын
Thanks!
@floatingblaze8405
@floatingblaze8405 3 жыл бұрын
I don't use Unity, but I find this really informative nonethelss, great video!
@aarthificial
@aarthificial 3 жыл бұрын
Thanks!
@bilel114
@bilel114 3 жыл бұрын
Thank you! More people should know this stuff, I love that you're sharing it.
@LutennantLongshot
@LutennantLongshot 3 жыл бұрын
Wow these are super cool. Love the mini tutorial on random stuff as well.
@peppidesu
@peppidesu 3 жыл бұрын
Pro tip: If you add two user-defined implicit conversion operators between T and Optional, you can just write Optional foo = 0.3f; Or just use a nullable type and use the majestic null coalescing operator for the job, like this: private Transform? target; private void Update() { DoSomethingWith(target ?? default); // or target?.position = new Vector3(a,b,c); // or target ??= default }
@aarthificial
@aarthificial 3 жыл бұрын
Thanks for the suggestion! Have you tested nullable reference types with Unity? I thought they where C# 8+
@andermium
@andermium 2 жыл бұрын
For anyone coming across this, I don't think the null-coalescing operators work, because they bypass Unity's equality override. It's an unfortunate consequence and they wrote a blog post on how they would probably try a different solution if they could start from scratch
@rasulseidagul
@rasulseidagul 3 жыл бұрын
Good job 👍, it is actually so much easier now to work with generics thanks to unity team. Previosly such things required a lot of boiler plate code. However, Imho, they could have done it waaay erlier(and yet they still didn't implement full polemarfism)
@zop5725
@zop5725 3 жыл бұрын
Oh dude, I have been looking a week ago, and found nothing good. Awesome Video!
@aarthificial
@aarthificial 3 жыл бұрын
Thanks!!
@rvv27
@rvv27 3 жыл бұрын
Don't use Null check in Update loop. That is one of cool performance trick that I learned. This is a very nice tip 👍👍
@verified_tinker1818
@verified_tinker1818 3 жыл бұрын
Expected something like Rust's Options, but this is even cooler!
@NeoN-bd3so
@NeoN-bd3so 3 жыл бұрын
Amazing, love your vids! Which Code Editor are you using?
@aarthificial
@aarthificial 3 жыл бұрын
Thanks! It's Rider
@Tantandev
@Tantandev 3 жыл бұрын
Cool trick! Was this inspired by the Rust programming language? Option is a built in type there.
@aarthificial
@aarthificial 3 жыл бұрын
Thanks! Now as I think of it, it could've been subconsciously inspired by Rust. I haven't used it in quite some time but I was always inspired by the way it handles nulls (by just not having them lmao)
@jbaidley
@jbaidley 3 жыл бұрын
Great tutorial. Clear, short, and to the point.
@aarthificial
@aarthificial 3 жыл бұрын
Thanks!
@dpeter99
@dpeter99 3 жыл бұрын
I'm sooo happy that I found your channel, these dev logs are great! Brought back my inspiration to actually make something maybe, but first back to my overcomplicated tooling You could also add some operator overwrites to the Optional class. For example auto convert to the value. Btw why did you use the old imgui based editor UI rather than the more modern UIElemens stuff?
@aarthificial
@aarthificial 3 жыл бұрын
I'm glad to hear that! As far as I know, the default inspector still runs on IMGUI so you can't use UIElements inside of it yet. Although I may be out of the loop on that one
@dpeter99
@dpeter99 3 жыл бұрын
@@aarthificial I think you should be able to do it. The editor uses a messed up way where the whole thing is UIElemens but the automatic fields in it are basically individual imgui containers. At least that is the case for the latest releases 2021.1 I think
@qwfp
@qwfp 3 жыл бұрын
Really nice concise video
@teamjoy1968
@teamjoy1968 3 жыл бұрын
Nice and short :>
@partially2k
@partially2k 3 жыл бұрын
Thx jacob - will be yoinking this ahaha
@aarthificial
@aarthificial 3 жыл бұрын
Np bro
@KingGurke98
@KingGurke98 3 жыл бұрын
I... don't really understand what you're talking about. But I'm sure I'll run into that problem you solved here, so this video gets saved ^^
@paulblart7378
@paulblart7378 Жыл бұрын
I’ve never seen anyone or anything say that a comparison to null is expensive. I’m pretty certain that “null” just refers to a special value meaning the variable refers to nothing. Is a null check not just a simple comparison of two values? I would really appreciate a deeper explanation.
@aarthificial
@aarthificial Жыл бұрын
Unity is actually a C++ engine and the objects we operate on in C# are just handles for the underlying C++ objects. The base Object class in C# overrides its Equals method so that if we compare it to null, it checks if that underlying C++ object still exists. This is done because the C++ object might have already been destroyed even though the garbage collector hasn't yet cleaned up its C# representation. So checking for null would return false even though the object is gone. This check requires an external call from the manage side (C#) to the unmanaged side (C++) which comes with a cost. In Unity, it's a rule of thumb to avoid these external calls in the hotpath.
@paulblart7378
@paulblart7378 Жыл бұрын
@@aarthificial Thank you! Interesting how the majority of youtube channels don't mention this and perform many null checks in Update(), myself included. I've never noticed any performance issues from it, so it surely can't be horribly expensive, but thanks for the clarification.
@nagybalint1474
@nagybalint1474 3 жыл бұрын
very useful thanks so much for creating this video :D
@DecrareOld
@DecrareOld 3 жыл бұрын
Interesting
@His-Games
@His-Games 3 жыл бұрын
and you can do an implicit operators to automatically convert other values into one as well!
@itsME-dc4vm
@itsME-dc4vm 3 жыл бұрын
Nice ;D
@ZiplawDev
@ZiplawDev 3 жыл бұрын
love it :)
@AngelofD000M
@AngelofD000M 2 жыл бұрын
You actually can make floats & int's null! All you do is: int? _integerValue; float? _floatValue; The question mark makes it null until a number is put in!
@aarthificial
@aarthificial 2 жыл бұрын
Nullable value types: 1. Don't work for references 2. The Unity inspector doesn't support them
3 жыл бұрын
I don't get it. What happens if you use an optional Transform target, but target is empty in the editor and enabled is true? You'd have to check for null anyways...
@aarthificial
@aarthificial 3 жыл бұрын
It depends on your approach For example, I never check for null if a field is required for the script to operate. The error thrown is clear enough to inform the designer what field is missing. In this situation enabling the checkbox is like making the field required In other words it's more about showing the intent that the field should be empty, rather than protecting the code from all possible values
@DaydreamStudios_Official
@DaydreamStudios_Official 2 жыл бұрын
Editor Scripts Are Great Too :D
@Thomason1005
@Thomason1005 3 жыл бұрын
neat tip, love it
@FranciscoTChavez
@FranciscoTChavez 3 жыл бұрын
This is really cool, but I have to wonder which one adds more runtime overhead: - Checking for null - Creating two property wrappers that causes two additional (and separate) stack allocation and de-allocations. After all, property wrappers are just functions, and every function call will do a stack allocation, followed by a jump to the function's code, followed by a stack-deallocation, followed by jumping back to code in the calling function. There's a reason why the performance experts at Unity suggest using fields instead of properties in your release code. So, if anyone were to take the time to do a performance analysis on this bit of code, I would be interested in reading the results. Besides, in my limited experience in doing performance analysis, I found that calling a function as a method parameter is a bit of a performance killer in the .NET Framework compiler when set to generating release code. I know that Unity rolls out their own compiler, so their complier(s) might be ok with passing a method call as a parameter to another method call.
@aarthificial
@aarthificial 3 жыл бұрын
Sorry if it's obvious but it's not about just checking for null. Unity objects override the equality operator and perform a transition from managed code to C++ (to check if the wrapped object still exists) which is why it's a best practice to not use them in the hot path
@FranciscoTChavez
@FranciscoTChavez 3 жыл бұрын
@@aarthificial I'm not saying that there isn't additional overhead to checking for null in Unity. I just didn't think I had to say that because you already mentioned it in your video. Besides, it's not that unusual to override equals equals operator in C#. This is an elegant pattern, but I would like to see some metrics that actually show that it's faster. I would like to see the metrics for the Mono builds and the metrics for the IL2CPP builds. I've seen some weird things with C# over the years that are counter intuitive to what I learned when I studied Computer Science. Last week I learned about the website called leetcode. They were kind enough to provide Runtime and Memory use metrics, so I decided to play around with the code in my solution. When I removed my temp variables and just used reused the input parameters, memory use went up by about 0.7 MB. And, the difference was not linear. With 2 temp variables, I used 28.1MB. With 1 temp variable, I used 28.7 MB. With 0 temp variables, I used 28.8 MB. It doesn't make sense, but adding variables to the stack, decreased my total memory usage. Sometimes, the thing you expect to execute faster, based on study and knowledge of how code executes, ends up being slower. I don't know if doing a null check is faster or slower, but I would like to know. But, in order to know, I would need to see some metrics to back it up.
@aarthificial
@aarthificial 3 жыл бұрын
@@FranciscoTChavez I suspected that much. I just didn't like how biased your comment was. Without, for example, mentioning the stack allocations that would be caused by the overloaded operator. So I wanted to clarify for anybody reading it
@bertrandguay-paquet3120
@bertrandguay-paquet3120 3 жыл бұрын
Hey cool trick! Be careful with using this at scale though because you're trading a single value with a value + a bool which increases memory usage. This will also generate a lot of generic classes that can bloat memory usage and code size.
@aarthificial
@aarthificial 3 жыл бұрын
Thanks! That's an interesting point. Do you happen to know how much memory a struct definition takes up? I've never faced a situation where the number of types in an application would be a bottleneck
@bertrandguay-paquet3120
@bertrandguay-paquet3120 3 жыл бұрын
@@aarthificial It varies with Unity versions, whether C# reflection is used with the generic class/struct and other factors so I can't give an actual number. I'm not saying don't use generics at all because they're very useful, but keep in mind that using generics has a runtime cost.
@abdullahshafqat772
@abdullahshafqat772 2 жыл бұрын
This is OP dude
@CaseyHofland
@CaseyHofland Жыл бұрын
I see a lot of lofty comments but I would like to point out as a dev myself that these quality of life structs do unnecessarily complicate code. In the distance example, you could (and in my opinion should) have simply said that a value of “0” means “unlimited”, which is pretty standard practice. The reason the struct is a bit frowned upon in this example is because you cannot as easily use your float in extensions and methods, because it’s a field of a struct. you can’t modify the field, you have to modify the struct now. These are all considerations you need to make when using the Optional struct: it has its uses of course but they cannot be too overhyped lest we regret our choices later. In these cases a “DisableLimit() => distanceLimit = 0f;” which some code to check for 0 is better practice in my opinion. Man here I go, I love your videos and the first comment I decide to write is nitpicking your code, I’m sorry I don’t choose to be this way :’)
@CaseyHofland
@CaseyHofland Жыл бұрын
You also “hide” your float inside a wrapper, making other developers anxious as to “what is going on inside that wrapper?!” Simple is often best, if for its clear communication alone.
@aarthificial
@aarthificial Жыл бұрын
It's meant for configuring things via the inspector. Editing a serializable MonoBehaviour field in the code is a really questionable practice. Still, value types were just an additional benefit, besides the main point of the video.
@chris.davidoff
@chris.davidoff 3 жыл бұрын
So I was thinking about this more.. Most null checks in an update loop are to safe guard against the object in question being destroyed.. Can you think of a way that 'enabled' could be set to false upon its GameObject being destroyed? (assuming `T` is a GameObject). I wish Unity provided an OnDestroy event instead of a message also, I tried replying with the link to the unity blog but it keeps getting removed
@aarthificial
@aarthificial 3 жыл бұрын
Oki, I was able to find the blog. Had no idea I was mentioned there Anyway, this pattern is more suited for editor-time configuration where things don't really change at runtime. That's why the struct is read-only. You can see at 2:22 that I mostly use it for value types and/or SOs. When it comes to GameObjects with unpredictable lifespans, probably something different should be used. Also, totally agree, an OnDestroy event would be great!
@chris.davidoff
@chris.davidoff 3 жыл бұрын
@@aarthificial I made an attempt this. Unfortunately, it relies on the user calling Initialize in an awake method, but otherwise it works! Let me know what you think github.com/RockyGitHub/OptionalT
@aarthificial
@aarthificial 3 жыл бұрын
Interesting idea! I think you could implement ISerializationCallbackReceiver and use the OnAfterDeserialize() method instead of calling initialize manually. Also, before adding the OnDestroyInvokeEvent component, I'd check if it already exists cuz there may be a situation where two structs reference the same object
@chris.davidoff
@chris.davidoff 3 жыл бұрын
@@aarthificial It appears that you can't access a "gameobject" in that callback, dang! That would have been sweet
@sonictrent
@sonictrent 3 жыл бұрын
When applying the property drawer anything else that uses the namespace of editor gives me errors, and without it the property won't show up in the inspector. I'd really like to be able to use this to improve workflow, I hope it's an easy fix.
@aarthificial
@aarthificial 3 жыл бұрын
Sorry if it's obvious but did you put the OptionalPropertyDrawer file in "Assets/Editor" ? If that doesn't work you can try changing the name of the namespace or removing it entirely since it's not required
@sonictrent
@sonictrent 3 жыл бұрын
@@aarthificial I have tried removing the namespace and having it in the right folder, I'm really confused why it doesn't work... I'll attempt it with a new project and see what happens, thank you for the reply by the way!
@crash1998100
@crash1998100 3 жыл бұрын
Have you actually benchmarked if it is faster?
@last8exile
@last8exile 3 жыл бұрын
Unity 2020.1+ needed to serialization of generics
@lilSapphireFox
@lilSapphireFox 3 жыл бұрын
Did they add the functionality to display a class with an generic class in 2020? bc i cant use it like this in 2019.4 or am i doing sth wrong?
@aarthificial
@aarthificial 3 жыл бұрын
Yes, unfortunately, generics require 2020.1+
@decidev
@decidev 3 жыл бұрын
Have you thought about making a discord server? It would definitely benefit your channel and allow people to talk to you without having to use KZbin comments
@aarthificial
@aarthificial 3 жыл бұрын
See, my crippling anxiety doesn't like the idea of people talking to me directly. I wanna try to overcome my fear at some point, just not today
@decidev
@decidev 3 жыл бұрын
@@aarthificial That's completely understandable. I'm always to scared to talk when I join a discord server so someone else has to initiate the conversation lol. But yeah I understand
@cil7ea
@cil7ea 3 жыл бұрын
I'm super new to C# and unity as I come from a different programming background. I know that C# 8 already has a nullable type... doesn't this mostly redefined that functionality? I understand that System.Nullable is not serializable, but isn't there a way to fix that? Why is comparing to null slower than comparing to "enabled"? Is there a way to force the language to use the same syntactic sugar of float? instead of Optional like maybe some operator overloading?
@aarthificial
@aarthificial 3 жыл бұрын
1) "C# 8 already has a nullable type... doesn't this mostly redefined that functionality?" Kinda. In C# 8 only value types can be nullable. Here the main idea is to use this with both references and values. 2) "System.Nullable is not serializable, but isn't there a way to fix that?" To the best of my knowledge, there is not. Maybe if we could apply field-targeted attributes to it. But nothing I'd know of. 3) "Why is comparing to null slower than comparing to "enabled"?" Unity is a C++ engine. Any C# object deriving from "Object" is just a reference to the underlying C++ object. Null comparison is overloaded to check if this native object still exists. This requires a transition from managed code (C#) to C++ which is said to be much slower than normal comparison. I don't know exactly why it is but I trust Unity on that one. 4) "Is there a way to force the language to use the same syntactic sugar of float?" I don't think so, especially since you're talking about a declaration, not an operator. But I'm more than glad to be corrected
@cil7ea
@cil7ea 3 жыл бұрын
@@aarthificial Wow, thanks for taking the time to give such a detailed answer. I was asking all this since in Swift (i'm coming from an iOS background) the "native" Optional type is an enum similar to how you implemented it but in Swift both value and reference types can be nullable. I wasn't quite aware of this C++ layer that might slow things down. I did read somewhere that sometime ago unity switched from mono to il2cpp but I haven't really found a detailed explanation of what that means. Most tutorials online just focus on the making of the game. I would love to learn about the intricacies of how unity actually works under the hood. Anyway, I love your videos! Super inspiring work. You make me wanna make things and learn stuff. That's an incredible impact that you have on people! You just made me become a proud patron :D Would you know by any chance any quality resources that might tackle some more advanced subjects about unity/C#/shaders (that don't cover how a for loop works)? Also, where would you think it's the best place to ask unity related questions? Unity forum, stackoverflow, some (your) discord group?
@aarthificial
@aarthificial 3 жыл бұрын
Thanks so much for the support! Unfortunately, I don't have any particular resources to recommend. Unite talks are definitely worth watching though, especially the ones by Ian Dundore. I think Unity forum would be the best place.
@realtimberstalker
@realtimberstalker 2 жыл бұрын
@@aarthificial There might be a way to add some syntactic sugar. I didnt see you add it in the video, but its been over a year so you may have added it already, you can define custom implicit conversions. That way, when passing it to a function, you wouldn't have do .value. It would also let you store a value into a Optional variable without needing to call a constructor.
@hetigamedev1818
@hetigamedev1818 3 жыл бұрын
Shouldn't you constrain T to something Unity can serialize?
@aarthificial
@aarthificial 3 жыл бұрын
I couldn't find a way to do that
@marijnstapert9036
@marijnstapert9036 3 жыл бұрын
C# doesnt have an optional type? Just curious java has one an JS has undefined
@aarthificial
@aarthificial 3 жыл бұрын
Since C# 8 we have nullable references (denoted via "?") which serve a similar purpose but I'm not sure how they would cooperate with Unity. In terms of a traditional optional container then unfortunately no, there's no default implementation in C#
3 жыл бұрын
@@aarthificial Spolier: the won't cooperate. If you check against nullable references you'll get null unity objects that evaluate as non-null. twitter.com/VehiclePhysics/status/1348641386573271040
@aarthificial
@aarthificial 3 жыл бұрын
@Edy García Oh, yeah, that's for sure. I was thinking more about the nullable aware context and how Unity's serializer would interpret something like: [SerializeField] private MonoBehaviour? mb; That is, if they're even gonna support that
@watercat1248
@watercat1248 3 жыл бұрын
after wach this video im sure the need to learn how to use the editor scripts
@alexjawny8705
@alexjawny8705 2 жыл бұрын
@ninosandlarz783
@ninosandlarz783 2 жыл бұрын
For those who tried to use optional variables in lists and encountered problems with indentation, you should reset the indentation to 0 as below: EditorGUI.EndDisabledGroup(); EditorGUI.indentLevel = 0; //add this line position.x += position.width + 24;
Dynamic Conversations - Legacy Devlog #23
5:27
aarthificial
Рет қаралды 60 М.
20 Advanced Coding Tips For Big Unity Projects
22:23
Tesseract
Рет қаралды 200 М.
Увеличили моцареллу для @Lorenzo.bagnati
00:48
Кушать Хочу
Рет қаралды 8 МЛН
А я думаю что за звук такой знакомый? 😂😂😂
00:15
Денис Кукояка
Рет қаралды 1,7 МЛН
The IMPOSSIBLE Puzzle..
00:55
Stokes Twins
Рет қаралды 158 МЛН
Better Coding in Unity With Just a Few Lines of Code
15:27
Firemind
Рет қаралды 316 М.
Taming Coroutines - Unity Tips
5:01
aarthificial
Рет қаралды 25 М.
I Made the Same Game in 8 Engines
12:34
Emeral
Рет қаралды 4,2 МЛН
11 Things You (Probably) Didn't Know You Could Do In Unity
13:49
Game Dev Guide
Рет қаралды 155 М.
Reimagining Astortion | Devlog 0
7:22
aarthificial
Рет қаралды 100 М.
Dear Game Developers, Stop Messing This Up!
22:19
Jonas Tyroller
Рет қаралды 729 М.
5 GREAT Game Art Styles for BAD Artists
5:00
Lost Relic Games
Рет қаралды 263 М.
A BETTER way to setup new unity projects!
15:44
Jason Storey
Рет қаралды 56 М.
One Unity Editor To Rule Them All
15:46
Warped Imagination
Рет қаралды 12 М.
Using Interfaces in Unity Effectively | Unity Clean Code
4:23
James Makes Games
Рет қаралды 62 М.
Увеличили моцареллу для @Lorenzo.bagnati
00:48
Кушать Хочу
Рет қаралды 8 МЛН