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.
@chadykarlitch2 жыл бұрын
100%
@FriedMonkey362 Жыл бұрын
I didn't even know u could do that in unity
@Sephta3 жыл бұрын
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!
@aarthificial3 жыл бұрын
I'll do my best!
@aarthificial3 жыл бұрын
@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!
@geekjoystick3 жыл бұрын
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 :)
@aarthificial3 жыл бұрын
Thanks, I'm happy to hear that!
@ariehuybregts98753 жыл бұрын
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
@octsonandivorgias70073 жыл бұрын
Short, Simple, and Straightforward. This video deserves more views!
@WingedOriTV3 жыл бұрын
This Dude deserves more subscribers and views!
@_kett21643 жыл бұрын
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!
@early2000skid2 жыл бұрын
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-3 жыл бұрын
I really like this solution. Easy to use, understand, and works perfect. Nice tip!
@Hoowwwww3 жыл бұрын
i don't use unity, but i love watching your videos, quality content!
@aarthificial3 жыл бұрын
Thank you 🖤
@chris.davidoff3 жыл бұрын
Found this from Unity's blog, and I'm stoked! I want to try benchmarking this to see the difference
@hazemsamy90583 жыл бұрын
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.
@aarthificial3 жыл бұрын
Thanks so much!
@RandomProduct3 жыл бұрын
Just discovered this channel. These are incredibly useful, and you've got a smooth voice. I could see your stuff blowing up, my dude.
@RandomProduct3 жыл бұрын
Also, after watching the pooling video, I gotta say your animations are so helpful in understanding these topics. Very well done!
@aarthificial3 жыл бұрын
Thanks!
@floatingblaze84053 жыл бұрын
I don't use Unity, but I find this really informative nonethelss, great video!
@aarthificial3 жыл бұрын
Thanks!
@bilel1143 жыл бұрын
Thank you! More people should know this stuff, I love that you're sharing it.
@LutennantLongshot3 жыл бұрын
Wow these are super cool. Love the mini tutorial on random stuff as well.
@peppidesu3 жыл бұрын
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 }
@aarthificial3 жыл бұрын
Thanks for the suggestion! Have you tested nullable reference types with Unity? I thought they where C# 8+
@andermium2 жыл бұрын
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
@rasulseidagul3 жыл бұрын
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)
@zop57253 жыл бұрын
Oh dude, I have been looking a week ago, and found nothing good. Awesome Video!
@aarthificial3 жыл бұрын
Thanks!!
@rvv273 жыл бұрын
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_tinker18183 жыл бұрын
Expected something like Rust's Options, but this is even cooler!
@NeoN-bd3so3 жыл бұрын
Amazing, love your vids! Which Code Editor are you using?
@aarthificial3 жыл бұрын
Thanks! It's Rider
@Tantandev3 жыл бұрын
Cool trick! Was this inspired by the Rust programming language? Option is a built in type there.
@aarthificial3 жыл бұрын
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)
@jbaidley3 жыл бұрын
Great tutorial. Clear, short, and to the point.
@aarthificial3 жыл бұрын
Thanks!
@dpeter993 жыл бұрын
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?
@aarthificial3 жыл бұрын
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
@dpeter993 жыл бұрын
@@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
@qwfp3 жыл бұрын
Really nice concise video
@teamjoy19683 жыл бұрын
Nice and short :>
@partially2k3 жыл бұрын
Thx jacob - will be yoinking this ahaha
@aarthificial3 жыл бұрын
Np bro
@KingGurke983 жыл бұрын
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 Жыл бұрын
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 Жыл бұрын
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 Жыл бұрын
@@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.
@nagybalint14743 жыл бұрын
very useful thanks so much for creating this video :D
@DecrareOld3 жыл бұрын
Interesting
@His-Games3 жыл бұрын
and you can do an implicit operators to automatically convert other values into one as well!
@itsME-dc4vm3 жыл бұрын
Nice ;D
@ZiplawDev3 жыл бұрын
love it :)
@AngelofD000M2 жыл бұрын
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!
@aarthificial2 жыл бұрын
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...
@aarthificial3 жыл бұрын
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_Official2 жыл бұрын
Editor Scripts Are Great Too :D
@Thomason10053 жыл бұрын
neat tip, love it
@FranciscoTChavez3 жыл бұрын
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.
@aarthificial3 жыл бұрын
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
@FranciscoTChavez3 жыл бұрын
@@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.
@aarthificial3 жыл бұрын
@@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-paquet31203 жыл бұрын
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.
@aarthificial3 жыл бұрын
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-paquet31203 жыл бұрын
@@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.
@abdullahshafqat7722 жыл бұрын
This is OP dude
@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 Жыл бұрын
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 Жыл бұрын
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.davidoff3 жыл бұрын
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
@aarthificial3 жыл бұрын
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.davidoff3 жыл бұрын
@@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
@aarthificial3 жыл бұрын
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.davidoff3 жыл бұрын
@@aarthificial It appears that you can't access a "gameobject" in that callback, dang! That would have been sweet
@sonictrent3 жыл бұрын
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.
@aarthificial3 жыл бұрын
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
@sonictrent3 жыл бұрын
@@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!
@crash19981003 жыл бұрын
Have you actually benchmarked if it is faster?
@last8exile3 жыл бұрын
Unity 2020.1+ needed to serialization of generics
@lilSapphireFox3 жыл бұрын
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?
@aarthificial3 жыл бұрын
Yes, unfortunately, generics require 2020.1+
@decidev3 жыл бұрын
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
@aarthificial3 жыл бұрын
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
@decidev3 жыл бұрын
@@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
@cil7ea3 жыл бұрын
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?
@aarthificial3 жыл бұрын
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
@cil7ea3 жыл бұрын
@@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?
@aarthificial3 жыл бұрын
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.
@realtimberstalker2 жыл бұрын
@@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.
@hetigamedev18183 жыл бұрын
Shouldn't you constrain T to something Unity can serialize?
@aarthificial3 жыл бұрын
I couldn't find a way to do that
@marijnstapert90363 жыл бұрын
C# doesnt have an optional type? Just curious java has one an JS has undefined
@aarthificial3 жыл бұрын
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
@aarthificial3 жыл бұрын
@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
@watercat12483 жыл бұрын
after wach this video im sure the need to learn how to use the editor scripts
@alexjawny87052 жыл бұрын
@ninosandlarz7832 жыл бұрын
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;