Unity Code Review - Refactoring Some Common Unity Mistakes

Поделиться
HTML-код
  • Опубликовано: 23 дек 2024

Комментарии • 119

  • @InfallibleCode
    @InfallibleCode  5 лет назад +8

    👉 Submit your code for a chance to be reviewed on my weekly Game Dev Livestream at infalliblecode.com/code-review

    • @mysticvalley4566
      @mysticvalley4566 4 года назад +1

      Can we get a link to James' channel/@'s?

    • @Glazzy0_2
      @Glazzy0_2 3 года назад

      @@mysticvalley4566 0

    • @Glazzy0_2
      @Glazzy0_2 3 года назад

      00

    • @Glazzy0_2
      @Glazzy0_2 3 года назад

      @@mysticvalley4566 0

    • @ziccodx
      @ziccodx 2 года назад

      This link doesn't seem to be working for me

  • @AndreiShulgach
    @AndreiShulgach 5 лет назад +56

    This is extremely helpful. Thank you! It's also really reassuring to know that a ton of the practices and fixes you both are making are things I'm already doing either through other tutorials over the past few years or my own trial and error.

  • @Kramlets
    @Kramlets 4 года назад +14

    Just so you know, transform *is* cached by Unity. There is no reason to create your own cached reference to the transform except for shorthand purposes.

  • @sebastianbryant4216
    @sebastianbryant4216 2 года назад +1

    Does the guy on the top have a RUclips channel, for some reason his word choice is extremely understandable when he explains coding concepts. This solidified some of my understanding.

  • @lovegeneration8464
    @lovegeneration8464 3 года назад +4

    One of the best 1 hour spended in relation to coding practices. Thanks

  • @ElvishJumpSuit
    @ElvishJumpSuit 4 года назад +1

    When your code is “tuned” it feels good. Knowing what you need to do is one thing, but actually getting on, and doing a proper tidy up, is the important step. If you never tidy up, you will waste more and more time reading over stuff. Each bit of new progress involves the extra work of reading over the untidy code, The desire to make “progress” often gets in the way of the “tidy up”. Some coders are lazy, and don’t care until they see a performance hit. Thanks for all the great tips. You guys are making a real difference here.......respect!

  • @yuvgro
    @yuvgro 5 лет назад +17

    Good Job guys, this is a great video for solo developers that never go through the process of Code Review by a fellow Dev!

  • @chriscollins8864
    @chriscollins8864 3 года назад +9

    Really helpful, reasonable and practical. Love how you explained THE REASON WHY the best practices are actually better!

  • @gegenton3953
    @gegenton3953 4 года назад +5

    This was extremely useful for me, even as a beginner. I'm writing what you call monolithic codes all the time, just because I'm not skilled/educated enough to think about good structure early in the process. I just want stuff to run. These refactoring videos are therefore very helpful! Also some smaller tips, like Unity.Random (booom?!)... loved it. Plus: you both come across very "explaining" rather than "telling what to do", which is much appreciated!

    • @scififan698
      @scififan698 2 года назад +1

      Pro tip: watch the 'clean coding' videos of Uncle Bob Martin and make yourself a better programmer in general. Far too few people take clean coding seriously, and if you're a coder, you should.. it will save you quite a few walls to run into. You're welcome 😀😁

  • @unitydev457
    @unitydev457 Год назад

    @39:00 "what is your first best practice that goes out the window when you're in a hurry" That's such a good question. for me personally single responsibility is what typically goes out the window under tight deadlines. Because often its quicker to bundle a bunch of responsibilities and logic into one class and one object and keep it tightly coupled to itself vs creating modular reusable components.

  • @scott_41
    @scott_41 3 года назад +9

    Noticed you replacing the types with *var* at 25:37. Microsoft recommends against it in that case because the type of the right side of the assignment isn't clear. It was correct as it was.

  • @coleslater1419
    @coleslater1419 4 года назад +9

    Absolutely fantastic video. A lot of useful insight. I Especially like that there are two of you bring different ideas and perspectives on things :)

  • @HomerJay
    @HomerJay 3 года назад +1

    I think, that invertion of the if block is not refactoring (7:30) and it doesn't make the code better. There's nothing wrong in having a "pyramid" of ifs, it doesn't make reading any harder. But i allows to follow the positive scenario and saves us of from an odd return which is somewhat similar to goto. If I remember right, Code Complete suggests to follow the positive scenario first instead of checking all possible problems and then (finally) doing someting useful. If you have a "pyramid" you see error handling in the very end of a method and it's nice because probably you don't want to read them at all.

    • @Glinkis
      @Glinkis 2 года назад

      Nested indentations is harder to read them a flat structure. Though I agree about preferring positive cases whenever possible. You can also have the best of both worlds by extracting a new method with the contents of each nested if.

  • @michaelgibbons2573
    @michaelgibbons2573 2 года назад

    your collaboration made me subscribe, for the first time ever! i´d love you two to work together more often. this was really nice!

  • @TerrenceGamington
    @TerrenceGamington 4 года назад

    Keep it up. Best Unity Coding Channel on RUclips

  • @day_that_i_die9854
    @day_that_i_die9854 Год назад

    Good job, guys! One thing I would like to mention is that, as far as I understand, one should use rigidbody.position and rigidbody.rotation while manipulating Rigidbodies.

  • @farahzehra8952
    @farahzehra8952 3 года назад

    Wonderful initiative that you guys have taken. Most freelancing programmers terribly need it. Please keep doing this. Wish you best of luck in all your efforts

  • @bluebukkitdev8069
    @bluebukkitdev8069 2 года назад

    Great video, I learned alot. I'm new to Unity and not as experienced with C# as I am with Java.

  • @mark3165
    @mark3165 5 лет назад +5

    Please keep up the amazing work! This is extremely helpful for learning coding in general 👍!

  • @donkeykong315
    @donkeykong315 Год назад

    Good stuff. I have heard before that using GetComponent constantly is not good but didn’t have a good understanding of why.

  • @domtech4104
    @domtech4104 3 года назад +1

    14:20 that comment about the Start function is auto-generated by Visual Studio

    • @MsSnoozable
      @MsSnoozable 3 года назад

      You can change what is auto generated, they talk about that

  • @RootLocusSquare
    @RootLocusSquare 3 года назад

    amazing watch. watching this video gave me so much insights in how to write better code and additional information i never knew. Keep it up !

  • @BlackPandaStudios
    @BlackPandaStudios 5 лет назад +2

    An awesome way to practice is actually code reviewing your own code/legacy code.
    There's code I wrote 6 months ago that I review now and just sit there asking, "But why?". And this has stayed true for the 3 years I've worked full-time in unity. BUT, please don't go overboard on this because you can fall into the trap of never progressing forward as you're just refactoring constantly 😂 Fun excersize though!

  • @ivanshakhov3759
    @ivanshakhov3759 5 лет назад +10

    Have you tried the Presentation Mode in Rider? Menus would become visible. Thank you!

  • @random_precision_software
    @random_precision_software 3 года назад +1

    Omg this is one of the best videos I've seen! Learnt so much

  • @DargothSoulfrost
    @DargothSoulfrost 5 лет назад +1

    As far as i know, transform IS cashed in Unity now. And has been for a long time. I think they did it somewhere around Unity 5 or something... You can test it if you're curious - there's zero difference between caching transform in awake and calling transform every update.

  • @kitsurubami
    @kitsurubami 2 года назад +2

    Thank you for this video. At my company I'm sort of isolated from other developers. There's nobody to ask "how would you do this code?" or "is this a code smell?". Not even 10 minutes into the video I'm learning about guard clauses and cyclomatic complexity. Guard clauses are something I've been doing for a while now to avoid "arrow code". I always felt a little worried that it was a code smell for the exact reasons you described here and now I know I can safely use it by extracting everything that follows the guard clause into a separate method. I'm sure there's many more things for me to learn in the next 50 minutes. If you Infallible Code or anybody else who reads this have good yt video resources on best practices, please recommend them to me. Thank you!

  • @NeoDragonEWW
    @NeoDragonEWW 5 лет назад +4

    Hey guys, I'd love to know why you use "var" instead of saying what type the variable is. I was always told abusing var is a bad idea and if working with a team it could be "what is the var? Is it a string? An int?" - you get me. So why use it?

    • @JasonStorey
      @JasonStorey 5 лет назад +10

      Well lets think about what var does, it removes the name of the return type and replaces it with a shorter cleaner name. could that be confusing? definitely but a common rule with software is the smaller the scope the longer the variable names, it gets to the point where variables have SomeVeryLongNamesInCode to describe their jobs. the thing is though, variables are a 2-stage process. there is the "declaration" and the "assignment/initialization" usually this means you are effectively writing the name/type of the variable twice. Dog myDog = new Dog(), etc. so in one of the above examples: var force = RandomForceVector(); we are writing the word vector... just doing it once, not twice. Var can be confusing if you have no reference visually to what type is. but is usually fine if you do. Lastly personally I don't worry about var because we live in a world of very powerful editors, and you can always hover over a var to see its "real" type, but in most cases you don't need an extra 3-4 words per variable at all times. var massively shortens your code and with vs or rider, you can literally press one keyboard shortcut on it to revert to a fully qualified name. TL;DR the goal of 'clean' code is readability. in my opinion I try to remove as many words from my code that do not add useful information to the person reading it, and if I named my variables well enough they should not need to know what the type is to read or use my code. even if they do.. its not gone, its one editor click away

  • @andrewhamel1
    @andrewhamel1 2 года назад

    I really wish you guys took the 5 minutes to implement the tower manager, would have been cool to quickly show the difference in the assembly etc.

  • @alphonsosensleyii7630
    @alphonsosensleyii7630 2 года назад +1

    This is a great code review!

  • @francispasive4474
    @francispasive4474 4 года назад

    I'm new to this channel. I love this live review. I learn a lot. I'm subscribing now with a bell HEHEHE

  • @Merlok_3_0
    @Merlok_3_0 Год назад +1

    can you please help?
    what is better: a lot of scripts having an Update, or just a few "initiators", that loop and update these scripts?

  • @tarutso
    @tarutso 3 года назад

    As a newbie this was so good and really eloquently and clearly explained. Thank you both!!

  • @raveheart58
    @raveheart58 4 года назад +1

    I wasn't aware of ContextMenu, thanks for the tip!

  • @titastotas1416
    @titastotas1416 2 года назад

    I almost pressed the like button once again to like it once more

  • @yummybunny7351
    @yummybunny7351 3 года назад

    25:50 what hotkey author use for capitalize 1st letter?

  • @themihanoid5020
    @themihanoid5020 4 года назад

    The only thing left about that GenerateRandomDirection part at around 35:30 that is left to do
    is to normalize it and multiply by constant of 10f (it seems)
    Then throw it all in a garbage can and just use Random.onUnitSphere * 10f.
    *I know probability distribution would be different but it clearly makes sense there.

  • @RosieSapphireMusic
    @RosieSapphireMusic 3 года назад

    I don't know why, but no matter how many times I watch these videos, and no matter how many times I think I understand it, I just can't seem to apply it to my own code.

  • @toadill
    @toadill 5 лет назад +22

    I would like to see beginners tutorials from you guys. We need pro education.

    • @scififan698
      @scififan698 2 года назад +3

      This is the beginner stuff..

  • @Faygris
    @Faygris 4 года назад +2

    This was unbelievably helpful 😊

  • @Treetopper911
    @Treetopper911 3 года назад

    What a fantastic stream! Thank you.

  • @LinkEX
    @LinkEX 2 года назад

    2:38 Ah, the infamous, nagging, overly intrusive alert sound of windows.
    _Virtually always_ heard multiple times in a row.
    Hearing it echo in the background never fails to raise my blood pressure.

  • @MaZyYTube
    @MaZyYTube 2 года назад +1

    I have to say I hate underscore. It takes two hands to write code if I use underscore and it doesn't look so clean. I use them only for properties to tell myself I shouldn't use underscored var.
    Also I never write private because its very easy to identify myself what is private and what not if modifier is missing.

  • @flaviokonti5522
    @flaviokonti5522 4 года назад +2

    Really awesome tips guys! Thank you 👍

  • @gareths
    @gareths 3 года назад

    You guys are really good at explaining things, wow.

  • @paranormalgamesstudios
    @paranormalgamesstudios 2 года назад

    This is gold dudes cheers!

  • @JamesClemones
    @JamesClemones 4 года назад +1

    Learning a lot from this, thank you. Re. the guard clause, I avoid them generally in C# and C/C++ for the reason you mention - they make code underneath harder to maintain because you de-localise flow control and have to mentally track it as a dependency. I think wrapping the code below up in a new function is messier and less efficient than just using the super-clear if slightly indented if tree.

  • @HenriqueSilva-ic1vk
    @HenriqueSilva-ic1vk 5 лет назад +1

    Another Question!
    You guys are awesome! hahaha Thanks for that content!
    An Empty Update() Function on a Monobehavior is "running"?
    Like "Update() { };"
    Is a good practice to remove empty functions like that?

    • @RivenX55
      @RivenX55 5 лет назад +1

      Yes, always remove empty Update functions if you do not use them.

    • @mehmedcavas3069
      @mehmedcavas3069 4 года назад

      I'm not sure I also want this answer. I would never do this but as far as I know, there are no benefits for performance because the update is a method from the monobehavior and its directly called from the parent :) Hope someone will answer so I get the notification :)

    • @SEF84
      @SEF84 4 года назад +1

      @@mehmedcavas3069 Back then I worked on something that involves on instantiating grid tiles on a level, like about 50x30 grids, with the grid prefab having a MonoBehaviour script in it. At first after everything's done I got pretty low FPS but it turns out that leaving the Update() method even though I'm not using it just because I don't know better is the cause, removing it makes the game buttery smooth again.
      In summary, remove Update() method indeed when not using it, hope this answers it!

    • @Aditya-us1qn
      @Aditya-us1qn 4 года назад

      Are you sure?
      Every class which ingerits monobehaviour goes through the unity life cycle right?

    • @Glu10Free_Waifu
      @Glu10Free_Waifu 3 года назад

      @@Aditya-us1qn unity creates a list of all objects that has update, lateUpdate or fixedUpdate...and then runs through it every frame...meaning even if its empty, it's still added to the list...
      So yea...if u don't put it in the script, it won't be added to the list...

  • @smallflyDE
    @smallflyDE 2 года назад

    More of this please :-) Who is the other guy by the way?

  • @Rhysman30
    @Rhysman30 2 года назад

    Oh wow. I've been coding in Unity for about 4-3 years. I just learned about "foo = foo ?? bar;" Is it just "foo = foo ? bar : foo2;"? But without requiring an "else" after the colon?

  • @n8dev
    @n8dev 3 года назад

    as of unity 2020.2 camera.main is super efficient, and doesnt use findobjectwith tag actually😁

  • @ironbard4901
    @ironbard4901 3 года назад

    This was beautiful, thank you!

  • @markomlakar6863
    @markomlakar6863 5 лет назад +4

    Great video👍

  • @ZaCkOX900
    @ZaCkOX900 4 года назад +1

    As a person that writes a lot of code. I would of told this person, extensions, the transformation and rigidbody will be used a lot like that. An extension makes sense.

  • @BurakNevruzoglu
    @BurakNevruzoglu 5 лет назад +2

    This is so valuable, thanks!

  • @Layarion
    @Layarion 3 года назад

    25:20 what is interpolating?

    • @scott_41
      @scott_41 3 года назад

      The transform's position and rotation

  • @Skdbszksixh
    @Skdbszksixh 3 года назад

    glad am watching those , thanks a lot !

  • @stevensavoie856
    @stevensavoie856 Год назад

    Though I understand how crazy computing power is, they are unknowingly making a case for their insistence on following good practices. They keep finding minor optimization after minor optimization. Many small inefficiencies can start to become large.

  • @TheRedAstro
    @TheRedAstro 3 года назад

    this was pretty cool, lots of practical insights

  • @KaanErayAKAY
    @KaanErayAKAY Год назад

    It was really helpful. Thank you!

  • @LeutnantJoker
    @LeutnantJoker 4 года назад +1

    Using ?? with components is problematic (probably ok with the camera though) since it is not aware of the null check override Unity is using. Null coalescing operators cannot be overloaded, so Unity cannot change their behavior. They only do a pure null check, they do not check if the object has been destroyed. That is still an ongoing discussion on the forums and a current weakness in the Unity API.

  • @CSPlayerDamon
    @CSPlayerDamon 5 лет назад

    Certainly lots of good practices. Just two questions:
    a) Why make a simple call to Random a whole new method? Is it because the method could be expanded upon later? I didn't quite understand it if you said it in the video.
    b)
    Though I too am a user of WaitForSeconds, I find it has one major flaw; it creates an instance of a class that needs to be garbage collected. Furthermore, an input of 0 would still yield, which would mean a loss of at least one frame. Wouldn't an ultimately better solution be something like this (not checking for negative time for simplicitiy)
    public IEnumerator WaitForSeconds(float seconds){
    float time = 0;
    while (time 0) WaitForSeconds(seconds); if you don't want a "missing frame".
    EDIT: Unless a yield return null also continuously allocates memory.. Wow, I really need to profile this one day...
    Anyway, I always found coroutines very intriguing and a fun way to build time-based systems in unity. I've even built an animation system based on them, since the primary function of waiting is a really powerful tool.

  • @HenriqueSilva-ic1vk
    @HenriqueSilva-ic1vk 5 лет назад +1

    Hey, About using Debug.Logs
    When you leave a lot of Debug.Logs in the code, and then build and run the program outside the Unity Editor, we'll have memory usage problems because of that logs? Or it is heavy only on the editor?

    • @BlackPandaStudios
      @BlackPandaStudios 5 лет назад +2

      This is heavy in the editor only 😊
      When doing development builds however, you can see error logs and hook up the console to the built application. But that's a separate thing.

  • @viveknishad5262
    @viveknishad5262 4 года назад

    do more videos like this. i m a beginner so i really need to learn a lot from you guys.

  • @mysticvalley4566
    @mysticvalley4566 4 года назад

    Can we get a link to James' channel/@'s?

  • @robertlowther7442
    @robertlowther7442 5 лет назад +4

    The fact that you are so uncomfortable seeing prefixes on functions is a great reason to use them for things like the coroutine here. That discomfort means that if you inadvertently attempt to use it as a regular function you will definitely see the prefix and realize the mistake you've made before compile time.I find that doing stuff like this that I don't like is a great way to catch my own attention later on when I return to a piece of code and don't remember everything that it should be doing.

  • @FernandoMirabile
    @FernandoMirabile 3 года назад

    Do you guys still think Camera.main is awful after last changes?

  • @antidotcb
    @antidotcb 4 года назад +1

    not only Groovy, for example Python not only public by default, but it's the only possible way. there is no protected or private in Python

  • @MsSnoozable
    @MsSnoozable 3 года назад +1

    You mentioned to refrain from too many if statements in Update. What else are you supposed to do? If you have a jump input for a player, I could put the jump function in Update, then the function still has an if for the jump input. How would I check for a a player's input if not checking for it every frame?

  • @muratbingol13
    @muratbingol13 2 года назад

    Thanks for this nice knowledges. İt's was helpful

  • @mehmedcavas3069
    @mehmedcavas3069 4 года назад +1

    Do u really need to cache the transform? I thought it is already cached after unity 5 came out

    • @JasonStorey
      @JasonStorey 4 года назад

      Yes, it is still worth doing.
      blog.collectivemass.com/2019/06/unity-myth-buster-gameobject-transform-vs-cached-transform/

    • @ZaCkOX900
      @ZaCkOX900 4 года назад +1

      If you cache it yourself, yes it is slightly faster but you could do that for other unity objects too. You don't have to and that's why unity allows transform. now

  • @Aristaeus89
    @Aristaeus89 2 года назад +1

    One practice I've taken up for differentiating coroutines is to just put an underscore prefix. So the method discussed in 30:00 would be _EnablePhysics(...)
    I found that it's pretty easy to understand from seeing it, as functions that start with underscore are very rare otherwise. But the main benefit to me is that it just looks weird if you call it on its own. But you get used to reading something like StartCouroutine(_EnablePhysics(...))

  • @sie85
    @sie85 5 лет назад +1

    The this keyword isnt required?

    • @InfallibleCode
      @InfallibleCode  5 лет назад

      Nope! docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/this

    • @phirewind
      @phirewind 5 лет назад

      Nope, it's implied.

  • @equious8413
    @equious8413 3 года назад

    I'm a scrub, but I'd learnt that starting a coroutine name with 'i' to indicate an IEnumerator was good practice to distinguish it as a coroutine.

  • @domedin9894
    @domedin9894 2 года назад

    These guys are to smart for me I’m still new

  • @flashpointstudios7910
    @flashpointstudios7910 4 года назад

    Apparently GetComponent() has a non-generic overload which is slightly faster, it is mentioned here: chaoscultgames.com/2014/03/unity3d-mythbusting-performance/

  • @00ZeroCoolGaming
    @00ZeroCoolGaming 4 года назад

    Here's the link to the talk mentioned during the video from the folks at Playdead: ruclips.net/video/mQ2KTRn4BMI/видео.html
    Still a great talk years later.

  • @patnor7354
    @patnor7354 5 лет назад

    Helpful advice :)

  • @CapnSlipp
    @CapnSlipp 5 лет назад +2

    `this.transform` isn't cached- it's hard-coded to directly return the Transform. This is possible for Transform (but not most other things) because every GameObject strictly has one Transform (or derived RectTransform) from initialization. Most components are optional; Transform is not.
    The full story is that a while back, Unity got rid of all the component accessor properties that were expensive, leaving only the ones that are cached and as efficient as any code you could write (which is just `transform` and `gameObject` in the latest version). So if Unity provides an accessor, use it, otherwise make your own cached accessor.

    • @vamvamcz8728
      @vamvamcz8728 5 лет назад

      You can write your own test code, that catched transform is a little bit faster than internal.

  • @herrflantier3739
    @herrflantier3739 2 года назад

    Happy to know i had some of those things right lmao

  • @lemurza5236
    @lemurza5236 5 лет назад +1

    Also F# and Kotlin, public by default. IMO its better to specify private

  • @Rhysman30
    @Rhysman30 2 года назад

    Some things being commented and some not, regardless of if its self evident, is a pet peeve. Not because it doesnt make logical sense, it's entirely a personal for things to match. lol

  • @vamvamcz8728
    @vamvamcz8728 5 лет назад +1

    Personally, i think "this.GetComponent" etc. is more readable than single "GetComponent ", just personall preferention to put whichone MonoBehaviour is calling the method. But good video to practice.

  • @marksnow8838
    @marksnow8838 2 года назад

    I wanna kiss the dude with the glasses, muah.

  • @hajji384
    @hajji384 3 года назад

    🤣🤣🤣 I'm very confused How fast he speaks this man

  • @Layarion
    @Layarion 3 года назад +1

    ew, that guys reverb is off the charts. i don't wanna keep watching this if that's what i need to subject myself to.

  • @brianjensen2532
    @brianjensen2532 3 года назад +1

    This has Brackeys all over it

  • @KrucLeo
    @KrucLeo 2 года назад

    Code review... Using Coroutines...

  • @Titan-8190
    @Titan-8190 2 года назад

    I learned a couple of things, like the log context. But a guard clause in Update is an absolute red flag, 99% of the time Update is abused and this is one of them. The _shouldAssemble boolean should have been removed with the update function altogether, MoveToStartingPosition that was extracted from Update should have been made a coroutine called from StartAssembly.
    Also the StopAssembly function that you added don't make much sense , I often see code with classes exposed too much, for exemple putting a public setter in every properties by default.

  • @hacker_man_sam5157
    @hacker_man_sam5157 2 года назад +1

    lol this is so dumb, this is all just micro-optimizations. Such a waste of time. Make games, identify bottlenecks, then optimized.

  • @Sephnroth
    @Sephnroth 2 года назад +1

    late to this vid, mostly loved right up to the summary/comment argument xD my stance is you are NOT a good judge of if your code is readable or not. You wrote it, you're automatically biased, you have context you don't even realise you have. "i've written this clean, its obvious what it does" is not helpful to the confused person 2 years later. I'm not saying comments should be everywhere, im just saying "code is where your code goes, it should be obvious what it does" is a mcguffin. Also, the most useful thing summaries do in c# is power intellisense - i often use them just for paramater decoration if nothing else!