Infallible Code - Unity 3D Gamedev Stream #5

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
going live I see loading bars I think we're actually live all right well unfortunately we had a kind of a rough start there but we're back I'm gonna drop a note on discord so hopefully you all come back into the stream but basically if you're new to this stream this is a game development stream where we focus on talking about programming unity and game development I will be taking your questions today and also doing a code review later on so first of all who are we and why do you care about what we have to say my name is Charles I run this channel infallible code I'm a game developer I do tutorials and videos about unity programming and game development and with me is Jason he's a prominent game developer he's worked on many projects and he's gone my prominence is preeminent he's going to help share his expertise yeah it looks like some people join in the chat thank you guys I'm sorry about the soft start there so if you want to submit your code for review we're gonna try to get to some today you can go to infallible code comm slash code - review that should be in the description if not I'll be sure to add that also if you would like to see the previous code review I just posted that up yesterday along with some clips so be sure to go on over to that video give it a watch give it a like and a comment and while you're at it like this video as well so we get some more people to join us in the chat so we've got some questions and topics lined up I actually made some show notes today but if you have a question drop it on the chat oh we got some first-time joiners welcome Blake and I and everyone else oh we got someone from Brazil hola almost us so um yeah how're you feeling today Jason after that rough start good I wish I had a beer I'm doing this thing where I'm only trying to drink on the weekends which isn't gonna last very long but I think if more streams start like this I might have to break that rule you know so well while we wait for some questions to roll through we actually had a question come in on the previous clips that I just posted check those out and that was about VARs someone was wondering why we use VAR instead of actually using the class name being explicit about the class name so for instance instead of saying string my name equals some string when declaring a variable using var instead so far my name equals some name so what do you think about that Jason uh you know man it's a very long winded opinions on pretty much everything Pacific Lee with this one I guess the hand way the answer is I like bars I use them in most cases I can and more detailed answer would be the main reason why is there's a lot of stuff a lot of best practice you would have heard before which doesn't really apply anymore when you take into account we've got some really fancy modern editors mm-hmm our IDE sort of take over a lot of what used to be bad practice so for example if the question so why would someone say var as bad first reason I don't I can't tell what the underlying type is well hover your mouse over the word bar tells you what the underlying type is so that's at being the main reason doesn't really apply anymore and for the whole sake of readability one comment I made before when you use bar you're predominantly doing variable declaration so dog-dog equals you dog right if you're writing the word dog three times all of our does is remove one of those declarations so providing you're saying VAR something equals create thing you're probably putting the word in there anyway so you're not really losing information either so I don't know just makes code look cleaner smaller less lines and if you look at the net benefit of writing var instead of you know list of pipe with generic parameter inside of it 30 times throughout your code you're gonna start to see a major shrink in size that makes it easier to fit in little screen easier to understand it just benefits all around yeah I mean and it's interesting because the answer almost feels on like unsatisfactory because it really just comes down to I guess you could say it comes down to preference it's just become the to use far and I think it really does come down to readability you know my favorite quote I finally pulled it up because I always butcher it by Fowler is Martin Fowler's any fool can write code that a computer can understand good programmers write code that humans can understand and that's what's really what it comes down to when you're writing code source code you want to make sure that another human and that of the human it may include yourself will be able to read and understand what's going on without having to encapsulate too much that in their own head and you know I've read code that I wrote six months ago heck two weeks ago and I've completely forgotten what I was doing you know and what the you know specifics of that code are so to be able to make it readable and make it something that I can follow is really important and what's interesting too is that readability you know maybe 10 years ago readability meant having syntactic sugar you know and following certain code style style guidelines on your team so that everyone is familiar and it's easier to follow code but now in modern era with things like Visual Studio and tell a sense writer really readability is enhanced by our modern tools because you know like Jason said you can hover over a bar and see exactly what it is that the VAR is so I think that's an interesting thing to think about and you actually approach it from a different angle than I was used to I usually hear the question is why use VAR but you were you actually mentioned like why is VAR bad I've never really considered that VAR was bad and there's a lot of stuff that sort of gets I don't know repeated his advice um and I've heard a lot myself where especially senior developers will say at the younger developers they'll say you know VAR is confusing don't use var it's hard to tell what's going on and I kind of think that the impetus to that is supposed to be don't use stuff you don't understand more so I think it's more a case of use the fully qualified words so that you get a sense of what it does and then use var when you understand it but I think I think that gets miscommunicated to just don't use var and I think that's a gross misunderstanding of the point of it you know yeah yeah definitely see if we got any questions in the chat a short answer can you publish the Tendo switch yes one of the one of the amazing things about unity is it's the most cross-platform game engine ever made you can pretty much deploy you can deploy a toaster like it's amazing it works on literally anything deploy to a toaster now that's gotta be a video yeah like I wonder what's what's the weirdest thing that you could deploy to the most obscure thing that you could deploy unity code to maybe like a car like a smart car I wonder if you I wonder if that's on the list that'd be interesting well I did watch a video recently where boom was played on a camera oh really was that unity or someone just but I'm sure I'm sure unity could make its way there so I'm going to ask them the chat where to submit killa that's gonna be infallible code comm slash code - review and feel free to click that little checkbox that says subscribe to the infallible code newsletter cuz I hear some there's pretty good information that comes in on that thing I made doom on my microwave well there was a meme about Skyrim you know about Skyrim being deployed to the most obscure things like I think one was like a refrigerator smart panel I'll say that that's very very few scenarios we're playing with this guy rim doesn't improve things though oh yeah someone says unity to support for Tesla I mean I know they're I haven't really I'm I haven't really looked too much into the Tesla I mean you know I know there's people that are like they really fanboy over it I mean I think it's cool but I did see some point recently where Elon was trying to get some of the classic games in the in the car much our our classic we're talking it I think the coolest thing about Tesla for gaming is he's got a scenario set up so that if you play any game that requires a wheel you can literally use your real oh that's me you can play a game with your actual you know your really your guy yeah Tesla has been using unity of port games to their screens inside their cars dude that is awesome now I'm ready I'm gonna get a Tesla now not that not the cyber truck though that thing I'm not so I don't know I'm gonna come onto the side of a fan of cyber truck yeah okay well we're gonna have some disparaging you know or both sides of the you know someone actually made doom for their Tesla outside of the company that's pretty cool oh they got cuphead working dang that's awesome you know look I need to get a Tesla now so I can have a cool video that I would go viral how to how to make it a Unity game for your Tesla oh my gosh that's awesome I wonder if it's an autopilot if you could play with the wheel you know a game that requires the wheel while it's just driving itself look if you're on the highway or something else maybe I was I was riding that system exclusive a few you wouldn't be able to accidentally do one of the other oh my gosh that's awesome alright well we got another question that came through on discord there's probably a couple in the clips that I haven't seen so you know again you know drop them in the chat if you have any but someone had asked trying to read this name Kerr kurenai's kurenai's sorry if I butchered that probably did asked about opinions on logic with UI architecture basically decoupling your logic from your UI or rather decoupling your UI from your logic so what are our thoughts on that what do you think I know you've got some opinions on this mmm-hmm yeah so this is one we've had a common amount of questions that are along the same line in the discord which is how do you get NBC working or should I use MVC or this kind of thing and I always have to put a pause on that and say hang on a second if you're asking how to use MVC you're asking the wrong question you're already at the point where you're trying to form a system around an architecture mmm when a point of a design pattern or in the case of MVC which is a composite pattern it's meant to solve a problem you're having so you don't have a problem that requires NBC don't use MVC to answer this question how do you decouple your view from your data it can be say MVC is this what it's for but in this case it's a it's very specifically to solve a problem so there's multiple ways to do it um you see MVP MVP M L or different choices but it basically boils down to figure out the contract for your user interface versus the data contract and then what is your business rules that sit in between them so look into the differences between those different frameworks I personally use MVP or when it's a very lightweight UI I'll use it's called the humble dialogue but it effectively boils down to that it's figure out your contracts and separate anything that touches the UI into one side anything which touches data into a controller that nip you lates it with the business rules you can actually perfectly cover that at some stage I don't think we've done a full deep dive onto MVC so I think we should no absolutely I think we should because you know it is a hard one and I think it's hard because there are many different approaches and I think it calls them to question a lot of other things that that come up with you need development for instance it's like Singleton's you know when you're trying to decouple your code in any situation but especially with you why because if you think about creating a game the UI is a huge part of that it's very easy to say well you know I don't know how to use I don't know how to decouple this and people are telling me not to use MVC fine I'll just use a singleton and then you probably get down a road where you're using Singleton's and then vice versa maybe maybe you're you don't even know about sine patterns you're just getting started out and you say oh you know I make this global when I can access it anywhere and then someone says to you one day hey no you don't want to use singleton so you're like oh shoot you start googling it what are you gonna what are you gonna do what's gonna come up when you google how to decouple your heart you're uiv MVC and MVC is one of those things where you read it and it's like wow at face value it really does seem to solve all your problems so I get it I get why NBC comes up all the time and then and then the other thing about MVC is that it is it does seem like the de facto standard what other there is there is no other one answer that really feels so satisfactory when it comes to how to dear UI I had never heard of what you call it the humble humble dialog that's my personal preference it basically plays out like MVP but you use a very explicit contract for the presenter so you inject a interface contract for the presenter and then you sort of marshal data back and forth so rather than using say your say you're doing classic NBC you use a command pattern and you'd have commands registered that would be called by the presenter to action things on the controller but if you're doing the humble dialog you actually delegate all of that to the controller so the presenter is a dumb terminal it basically just takes data and then asks requests to the controller to say please do this and then the controller makes all the logic so it's kind of a in the land of if we're talking about extremes you'd end up with your standard class is one thing then you move up to mvvm which it decouples half and half they move up to NBC which has your triple-layer decoupling and then MVP would be the same thing but you were more lightweight on the presenter side and then finally you get to humble dialogue and that's where you do something like a dialog box it's kind of the traditional case where you have a really really lightweight presenter and that way you can slap multiple faces on the same controllers so yeah that's that's a very deep topic I don't want to like that's something we should actually make a video on because I I could I could talk for four lengths about the differences between each kind of nuance thing and if you're not very familiar with them they don't look very different if I was there about MVC and MVP together a lot of people go well what's the difference and it's like well it's down to direction of data flow like it's hard to describe visually what that is until you actually present a problem and why that would solve it you know yeah definitely definitely yeah that's something we're absolutely gonna cover so yeah keep an eye out for that Matteo thank you for the for logging in just to give us a thumbs up that's why you earned yourself an emote everyone else would like to join them and thumbs up the video that would be greatly appreciated yes yes very very much so we got a super chat thank you in and out in the last video Jason suggested cash the weight for seconds was that because the frame rate will drop or is it because it's unnecessarily allocating memory on the heap I never know which optimizations are for CPU and which ones are from memory memory you're right on the allocation it's basically the fact that I don't know first base basically the problem I have with a lot of unity stuff is if you've worked with unity predominantly and knocked on classic c-sharp stuff there's a lot of sort of the the fundamental ideas that you miss out on and one of them is the fact that the word new is literally allocation it is instantiated something and creating it and you know we're obviously familiar with garbage collection and unity but it if you actually pause for a second and think about it every time you see the word new that is creating something and in the instance of a while loop or a for loop where you're doing a go routine and returning and you anything ask yourself do you need to be creating that new object every time you return and in the case of Akko routine you're usually setting a duration value or you're setting something where you're you're doing it one time and you're saying for example spawn B's every four seconds so that four seconds is a wait four seconds of four you don't need to create a new wait four seconds for every single frame you can just create that once at the start at the co-routine reuse the same one so there's also other things to do with just running a co-routine if you return values it's gonna actually skip one call anyway cuz that's just the way it works it's iterating through on the updates so there's other reasons too but the fundamental one is just simply if you're using any value and it's the same value for more than one update cycle don't use new and it just happens to be that's a good candidate in the middle of a go routine would it be worth it to switch to the code editor and kind of give an example that I have all these fancy switchers might as well use them right let me yeah Fred I can imagine a lot of my rambling is hard to hard to visualize though probably the help of it all right let's pop on over there alright so now we're looking at well this is the script we're gonna be code reviewing but so I kind of set up this test amount of behavior so the idea is that we're gonna have a guy named writer yeah and we'll just do a single while loop so I'm gonna I'm gonna do it like you like to do it Co underscore so we'll call this yeah just my routine or something like wait for the take take in a little load call duration that's all the really matters for this yeah yeah so a common example of this is you would sir I'm sure oh it's not him on a behavior that's why I was trying to add that start method I know that wasn't anything it tells right sorry go ahead yeah so I'll just saying if you did if you did a while loop so while true don't even bother with with conditional logic for now and just inside of that just right return you wait for a second wait return new waitforseconds yep now on the next line make a function called do something okay and that's an eye enumerator not a night I innumerable oh my bad and do I see as a yield statement for yeah yield return yet alright so this is a very kind of standard approach you do in community and it basically says wait for X seconds do a thing wait for X seconds do a thing and loop this indefinitely and then when you decide you wanted to stop usually in like a on destroy or on disable you would then stop covered in this actually this is a good point to cover a couple of topics over here yeah the first the first one is well fact we've got the word in you there on line 15 means it is mooing up some item every time it hits this while loop and as we can see it hits this while loop pretty frequently because it's forever so if you just move the new portion out up above line 13 or I should do my refactoring what the heck happened there yep yep that alone now means your instantiating at once now obviously that's not capable to do if you train it at multiple times of duration changes you cannot update a wait for a second but if it's something like this where you're using the same value for the duration of the cover tini this just saves you allocation right now next up if you're trying to start and stop a co-routine a bad practice I see people do a lot you still do this and then for example it can make a function called start routine hey you know what I'll just your hands and call our call our echo function one second owner actually we want this to go for on our way yeah one second yeah so this is this is an approach I see people do a lot but they'll start a curtain and then when they want to stop it so make a function called stop routine just stop routine yes people say it stop all I think there's stop all that yeah yeah stop Walker teens do they do that or they do something similar to it or they stop by name you can type in the name of the goroutine mmm I usually don't recommend either of these yeah you can say stop routine in the past in a string I think there or a stop that's ours that there it does recursive stop - yeah stop Cortina sorry yeah and what you passing it's a strain for the name of the actual thing I think is one option oh you saw them tell sense oh let me just show you for a second okay like that in ooh nice based on the fact that I returned and I knew or enumerator so I think people do this and as a general rule whenever using magic strings you have to you have to think about how that's resolving but the code is going to have to do some magic to take that string iterate through your script find the object do it so you can imagine there's some work going on there work that you don't need to do cuz you're the guy who made this you know you know what the actual least bit of code is so what you can do instead is you can cache the routine prior to calling it so the way I tend to do this is if you go to line 10 and create an eye enumerator local variable mm-hmm and I call it underscore routine myself but it doesn't really matter what you call it and then above line 15 you assign it and then just cut our bit there yep do that and then just start on this core routine so it does the same thing it just memories we've cached that object which means when we go to stop it we can literally stop it as a variable and that's pretty handy but it adds an extra bit of benefit that we wouldn't have had otherwise which is you can put a line above 15 and say if routine is not equal to null stop go hey sorry yep kind of ugly let me wrap it still it's easier to read oh nice now is that basically means every time you call this function your console in the previous routine is starting the next one because what will happen sometimes the people get really confused by those they'll run a core routine we'll say it lasts 5 seconds they will then hit the should've run it again the last one might still be running for the duration of the next one starting and you're getting conflicting values so you might be setting the position and it's basically a kind of like a race condition mmm and this gets really weird so say you're setting the position to interpolate from A to B if the last one is halfway there and then the next one starts it's going to jump between those two points as the two protein two routines update calls are happening this way you force the previous one to stop before you start the next one I see here where someone was mentioning that start coding actually returns an object that you could you could cash yeah so I guess if you if you really wanted to an alternative would be saying routine equals start ko routine which I don't really like using strings well I guess you don't really need to you just call the method cool yeah yeah that's an option too all right personally I'd like to be more is complaining I don't know boys oh wait so there's actually an object called co-routine there is yeah so kind of the same same idea but I guess maybe it's just that I'm very familiar with the numerators I like I like living in a numerator space because I know what's that like to be able to stop it as a especially when you get the later stages where you start doing things like using numerators inside of numerators and you can then return their values yeah yeah yeah it is kind of nice to stick to stick and stick to the unity kind of ecosystem but I agree with you there I much prefer well it is also nice to have this kind of one-liner yeah well I don't know I we talked about this in a previous stream I think about functions that do more than one thing like this starts the KO routine but it also returns something you know what I mean so whatever I guess it's at this point it's up to preference okay I guess that's the other thing too is that maybe the reason I'm averse to that is semantically start co-routine implies an action of starting something not a guess or create and so linguistically it doesn't flow as nicely for me yeah I prefer this method to even though it's a little more verbose it's like you're going through all these steps but it is it's very explicit it's like and also like that's a very common repetition cycle so actually have that and a helper class myself I was just gonna say like we should you know I feel like we should encapsulate this into a helper class and yeah definitely definitely would you make that a static class or would you make it a again I'm sort of I try not to use that at classes work even really possible something like this is I I actually I'd we're not getting too much into it I have I have a class which manages runners for running things like a numerators the reason being is if you think about it all the numerator is is a series of steps with a weight call it basically says do I have more steps to run at Doig more steps on it which means you could theoretically run in a numerator either in a co-routine or in a thread and so if you design a interface for a runner a runner could be a co-routine runner or a threaded runner you can talk about depending on the use case so dargah so frost made a good point that you know you could technically also cache the weight for seconds just like we did the an enumerator recording the the problem here is that we're passing in the duration so yeah like if you got one duration for the literal duration of your scripts life cycle and short but I find in most cases the duration will change for each call yeah yeah I feel like I know Ronald I mean I may be a constant I was thinking like hard coding a value in here but you could just make it a constant but yeah yeah I mean in the case that you have a constant value in here sure you definitely or read-only value you could definitely catch it at the class level yeah so cool so that's a that's one of the basics with quarantines although in general it's worth for people who don't know it it's worth noting that goroutines are not asynchronous Wako routine works is it's think of it as a list of steps you have a task you want done and you can slice it up into steps using the yield returns and so all that it's doing is every time you call yield return it's waiting for the next update to do the next step so it's it's divvying at work it's not actually doing it a separate thread which depending on what you're going for that may or may not be helpful well so thanks for the question there in and out this was a great I'm glad we were able pop into the code we got a question that's awesome because I have a video coming out about it this Sunday so the question is what do you guys think about the state pattern used as an architecture basically building a game treating almost OS actually it's a little different treating almost everything as states states of player states of enemy states of gameplay so right now I mean the video that I've come out on Sundays just generally about the state machine just to kind of talk about it but yeah what do you think about that using state pattern as an architecture for everything so I'm gonna put a I'm gonna put a warning out there and say be very careful about this because what you're describing falls into a category of what's called a rule engine mm-hmm and we end up getting into this category where what you're doing is you don't realize it but if you take a step back and look at it you were building a language on top of the language you are using yeah we're building a language of actions and a language of so if technically they're called predicates and actions if you're effectively building rules that you sit on top of your code and you can stitch in different ways and that's really cool and I'm pretty sure every programmer ever at some point has done that because it's really fun once you realize you can build commands for everything why isn't everything a command if you do that and then you realize all of your logic starts to be built in the nesting of your commands and you start doing things of composite commands where you're putting commands of commands and then you put a condition in front of a command and then you have a condition which decides which commands are instantiated and other commands and all of a sudden you step back and go I built a system with infinite power but I now don't understand what it's doing and I hate using it when you stop and realize that you're like oh what have I done and so to answer the question of state machines state machines are literally designed for internal state theoretically your state machine the rest of your code shouldn't understand it's there mmm you use a state machine inside of a class it could theoretically not use a state machine and nothing else in the system should change and the only other reason to use command patterns like that would be if you're doing something like a history with an undo and redo or you're doing an actual command stack or in cases of doing some UI stuff where you want to use decoupling using the command pattern so long story short if you're building your workflow of your application via commands you're definitely using the wrong pattern you're using them for AI you should probably be using something like a behavior tree if you're using them for UI events well depending on what pattern you're wrapping it in maybe you should or shouldn't be using them but that comes down to whether using MVC or whatever else it basically boils down to don't let yourself accidentally build your application through stitching commands now let's say never use them there's some really cool stuff you can do and the example I tend to use is I use commands for discrete actions so for example in a game I might have a shoot command and something would build that command and stitch it together but I wouldn't I wouldn't build logic into my commands I would just end up with a factory that would create commands and then apply those commands to things so don't let your commands literally build your application yeah yeah and it's it's one of those things you know and it's so funny how it I don't know if it's a thing that happens with game development or specifically unity but how you know it's so easy to snowball out of control when you you know you find something like Singleton's and it really does seem like a great answer and all of a sudden you're using them everywhere and then you got like state the state pattern it's a great pattern but then all a sudden you're you're using it to architecture your whole game you're basing your whole game then you start nesting States and it just gets out of hand and I think a good rule of thumb is you know they're I mean I think everything requires a hybrid approach you know if you're thinking already like I'm gonna build I'm gonna base the whole game on the state pattern or the whole game on like MVC is something we just brought up you guys sit back and say you know you're really locking yourself in that's another thing that comes up with ECS is that when you use ECS you really lock yourself into one architecture that you know your whole game is coupled to and it's very hard to break out of that if you ever need to break out of that yeah the video that I got coming out on Sunday I highly recommend you all set your calendars I haven't figured out what time so I'm still working on my weekly schedule but yeah it's gonna come out Sunday it's basically gonna be out state patterns and what Jason said earlier is pretty prevalent to the video that the other systems in your the other classes and pieces of your code shouldn't even know that a particular class is using the state the state machine architectural pattern and you'll see that I take a take an actual bit of code that has states that are encapsulated as enums and I basically refactor it to use actual States as the state machine pattern instead so keep an eye out on that isn't the job system the unities approach to multi-threading I'm not sure okay this is a thread that I've been seeing roll up in the chat about async asynchronous code in unity someone had asked earlier you know can unity handle in say sink await and currently it cannot the job system is kind of unities approach to multi-threading I mean not kind of it is it is multi-threading and it's still in its early stages I think they renamed it two dots recently which is I forgot I think it's data oriented technology stack is what it stands for and the idea with that it's very closely related to how they're developing ECS is that you can take take your code and you can basically chunk it chunk up your logic so that it operates on large sets of data and it's one of those things where the you know they they they tout it as it's great for mobile because it saves battery life it's great for things like boid systems or games we've got a lot of objects you know would they have to keep track of and it's very memory intensive but at the end of the day I feel like it's just a tool that a lot of people look at very much like MVC I know we already brought it up and say oh wow this is the solution to all my problems I'm looking to optimize my game das is coming out okay I'm gonna wait for the jobs to come out so I can develop my game I you know I would say don't rely too heavily on it I know that wasn't the question but uh you know I just I just happen to see that a lot when I when I see people talk about the job system you know and discord servers or like in forums people get really hyped about it but you know it really is just a tool at the end of the day too optimize certain parts of your code that need optimization and I would say I don't know what you think about this Jason but I just I can't think of very many things that I've written or implemented that actually require that level of optimization yeah yeah that's the real crux of the situation right like I I'm one of those people who will happily hands up say unequivocally the dots approach is going to be the best for building large games just it just is it's just better than using a standard operand approach it's gonna be better for I don't get though many reasons why but it's fundamentally just better what you might need it and to be honest this is something that goes through for all the stuff that we talked about all design patterns everything else don't just use stuff because you think you might be if you're for example building a demo application to test something to show a client don't build an 8 layered architecture you don't need it you know and the whole the whole sort of hyper optimized for mobile thing is great if you're building a mobile game that requires hundreds of concurrent users or you're spawning armies to fight each other if you're building a two-player tank mini game you don't need it and there's no point in sort of over engineering something for the sake of you know performance gains that are not really gonna hit on the devices you're running with the kind of stuff you're doing so is it going to change the way we make games going forward probably is it going to change the way I work on a nine-to-five building client apps and building stuff for kind of demos and for to be honest the majority the stuff I do was marketing material but no it's not gonna really change that because most of these stuff are for tradeshows and it's a trade show where it lasts for three days it's the show off some feature or mechanic or system or something and it doesn't need me to go and build a hyper robust you know architecture for it but what if hypothetically I was building an MMO then go go do it nice yes go do it over there don't tell me about it before tunic aren't you gonna back my my Kickstarter come on man kickstart me out at the door that's an all right cool I had a question come through I see about oh where did it go Oh what are your thoughts about using scriptable script scriptable objects as a place to store some state for example storing the playerhealth someone he says isn't it essentially some sort of singleton and it's yeah it's interesting a way to look at it but you know if anyone's seen I'm sure most of y'all seen Ryan hip pulls talk about scriptable scriptable objects why is it so hard to say scriptable objects um it's it's a way to encapsulate and share the data I never really thought about it as like a singleton but you know I guess if you think about it it kind of has some of the same properties of a singleton that you should you know well you know I guess saying it's persistence and saying it's the single doesn't stretch to say the two but sure like I do I certainly get the sentiment and sentiment is it's a persistent object that stores data I think it's a good idea yes I use them a lot like a lot a lot a good example is I use them for configuration data I use them for saving preferences and settings lots of stuff like it's one of those things where it works for like you've got a shop in a game it's got a list of items fantastic bird you can encapsulate the concept of the shop persist the shop name and its details and all the entity data you need and what objects are in the shop it's fantastic echo teens are effectively in monobehaviour without a lifecycle you've got some of the lifes like you mean scriptable you said co-routine scriptable lab one thing i would say to be careful of a lot of people kind of missed the point of what people objects are for their for persisting data which has multiple variants so the point of a script full object is when you have five kinds of shop for example they're all the same data just they might have different parameters or settings or you build a Boyd system or you'd built a simulator and that simulates you know ships flying or something like that you would then have settings for velocities and acceleration rates and turn radiuses and you could then configure multiple settings and they're like a snapshot of data you could swap out if you're only going to use that thing once it's kind of a little bit redundant to use the concept of buried scriptural objects to do that if it's just a couple of fields I purchased it the normal way or I would just save it out as a text file or a CSV or something if it needs to be secure and there's ways to secure that with you know hashing things and using a hash key for comparison and that kind of stuff yeah I don't know scope objects one of those things when I first heard of using unity for the first year and a half I never used them I got all I didn't they were just a feature of unity I never even bothered looking into it someone convinced me to sort of go and give them a good look and I did and I realized oh these are this is literally unity solution to persistent data so I should be using it when I'm needing persistent data in unity so it's pretty much there that's what they're there for works very well yeah so when did you if you're trying to persist data when do you think you'd go to the trouble of saying fine I'll just I'll do a save to a text file or it's like a DAT file or something I go why it's almost seems like if I was a beginner and it said why wouldn't I use scriptable objects it seems like the perfect solution so what I tend to do is I use scribble objects as my first step those cases mm-hmm so if I've got data of any kind whether it's items in it again I have in a shop is such an easy one to say it's a wallet for a user in a game or the the default health and weapons status for characters or something what about player health like like was mentioned before keeping track yes player health is good but another thing I say is you have to be very very careful and be aware that it persists between loads take off your Flair's help and launch the game again they will only have half health next time around that might be what you wanted that's the game you're playing yeah if you're free loading your level you have to make sure to reset your values when they need to be done yeah sometimes just saving the data isn't enough you want to save like state like level like for example save whether they've achieved certain goals or that kind of thing as for when and where to use it well if I've got data I usually some sort of data store or repository and I would say save settings save the the the highest level two players achieved I would go to level manager doc set current level that are passing a number that would go to some repository and it would save it and that repository would start with be a script full object one so easy to set up it's just one script like and I'm all of my data persisted and I can just continue building the app and never think about it again until the time comes where I want to test that data or I want to spit out multiple versions I might make a different repository that is CSV based and I can save that files I can share them I could load them in from paste bin it doesn't really matter it just gives me a bit more freedom to what I want to do and then as the project grows some more we now want to get to the point where it's sort of more representative of large-scale data I'd swap to SQLite and it's the same thing and I'd do all of this at the repository stage so when would I go from scribble object as CSV well there hits a turning point where you start adding a lot of data to a scribble object and it stops looking it starts looking like it's doing too much work that's usually about the stage it's sort of a good instinct for than anything else you know it's interesting how scriptable objects are kind of like they represent to me like implicit persistence whereas you know if you actually roll out something like a repository that's more explicit persistence because you have to explicitly say I'm saving here and like you mentioned with playerhealth you might say hey look every time there are the level reloads or whatever the case may be we'll just set his health back to full health but if you're using a scriptable scriptable object to persist that hold that data then now you actually have to explicitly reset it when the level starts over or you know when maybe when the game awakes or whatever the case may be instead of saying hey look I'm only going to persist this data explicitly if in this part of the level the player hits ctrl s or hits say whatever however they saved the game or gets to a checkpoint whereas with scriptable objects it's just persisting all the time so you know I could I think that could have some side effects that people don't you know may not consider in the case of using them as a player health that scriptable object is essentially a reference to some data I think this is very useful if you're using the humble object pattern and you actually can create just an instance of some class that has the value interesting okay yes I see what you're saying there one thing I think I would like to point out because there's a couple of questions in the chat that sort of they're all based around the same idea hmm sort of comes up as the the little adventure I laid out there where I start with fitful objects move to CSV and then move to SQLite or something I really want to make something very clear here data formats are not sacred and this is something I see a lot of people get wrong when they start building these kinds of systems is that last question like what is the right way to store user data for my game they will they're basically looking for me to give them the answer you should use Jason here you should use XML here you should use SQLite you should use SQL Server you should have a MongoDB database and connect to an API whatever and that's not how it works there's not an answer for the right way to do it the fact is it you've got a requirement for your application I need to save data do I need to persist this on the local device then your requirement is to store it in some sort of file that can be reread even if they don't install the app is it I need to look through all this analytic data at some point down the line then your requirement is I need to store this as a group off-site so I can iterate it as a single set if it's I need to persist this between multiple devices or like Steam where it's multiple installed instances on different machines then your requirement is a file format that can be sent and pulled back and reload it across multiple devices and kept in sync so there isn't going to be a right answer for what the right file for my there's stuff that you know he leans into like player prefs and triple objects and there's stuff that's more native C sharp like JSON objects or XML files or CSV files or I know Rhys text file doesn't matter it basically bows down to you can do whatever one you like providing it conforms with the requirements you have if your requirement is to secure it so people can't edit the data in an external text file you might have to do some encryption but that's a different requirement so don't pick randomly based on I here Jason is faster or I hear you know you should gzip all of your API calls like these kinds of statements don't really mean anything unless you have a environment to put them in and this comes back to what we're saying about the game when it comes TCS don't just do ecs because that's what everyone says you should do use it if your requirement is I need this to scale for mobile with lots of entities like lots of particles so there isn't the right data format and it doesn't matter if is X right for my use case we'll ask yourself what does it do what I needed to do and can I use it yeah and I'm seeing a lot I've seen some comments in the chat about the solid principles and and really that's kind of what that's kind of the crux of it you know you're trying to write code that is robust and flexible for these cases so that when these questions arise you can say to yourself you know I don't need to answer this right now or I can I can put this off until I know what my requirements are you know to putting something like a repository to abstract out the data layer is important when you're at the beginning of development and you're not really sure maybe you're not sure where you want to store it or how you want to store it or what the requirements are of storing it like like Jason said I think there's some great examples of things that people don't necessarily think about does the data need to be encrypted does the data do we need to perform analytics on the data later on to determine you know how players play our game or maybe there's some sort of monetary benefit there maybe you have I don't know sponsorships like littered throughout your game and you need to be able to track where the player was and if they saw certain billboards I don't know just contriving an example but you know that's an example where you don't know how what the data is gonna be used it's not at face value you think yeah sure I need to save data so that the player can you know play the game later and get access to the state that he was in he or she was in but then there are so many other things to to consider as well and that's where the importance comes in and abstracting out that section of your code and also writing your code in general solid and clean and you know all those fun words we'd like to throw around there's a reason we we throw those words her around and I think it's like requirements changed to write different different formats scale for different reasons so if you're building a analytics tool that's tracking user position or tracking data or you know logging things that are going on the plain text file is really good because you can append to the end of a text file really quickly just open the text file appender line close it you don't have to really care about reading those care but anything else and even meet it you persisted your data there's some lock issues with with reading text files and depending on your platform and stuff you might get some issues that's a really quick thing that works opposed to that though if you're trying to search a text file you're gonna have to either iterate through every single line of it or read the whole damn thing into memory and in both cases there's downsides to that reading for each line is usually better because you don't have to keep the whole file in memory but either way that they're different solutions we have a problem if you're if you're trying to recall chunk of data for searching something like SQL say just a local no sequel they know the local SQLite database is probably better restoring like lots of weapons and objectives and characters and stuff text file isn't great there so the the the format you're using is kind of dependent on what your requirements are and so if you put in an abstraction layer that's not too complicated just a simple abstraction for Oh save the orcs and I mean like savers and save the data it don't save them or go save the user data or log play your move position log at player got achievement laga you just build an interface that does that you can then choose the correct saving method that will be best for whatever is you're doing and this list is this ethos is universal across all our programming the same thing goes for if you're talking about collections there's a in one collection to choose from there's the obvious ones like list and raise you can get two stacks and queues and array lists and hash maps and hash sets and whatever else and there's there's pros and cons depending on which is faster or slower whether you're reading writing searching or you know iterating or whatever so if you can build an interface which is literally what ienumerator is that lets you iterate through a collection of items you don't have to worry about which collection method you're using to solve the problem of iterating through them because that's just you iterate through them you get the items you want there's the solution of what's the best data format the store in comes down to someone else's problem that's like somewhere else in my code I will decide that the stack I will decide that's a list so again there's no right answer to these things like a lot of these questions come down to should I use this is this the right answer should I do this it doesn't work like that it's more ask yourself what it is you need to do look at what's available options for you and then pick the one that best suits what you need yeah and one of the things that I've heard in the past is when you come to a decision point where you need to decide between two things for instance you should always choose the thing that's easiest to change later and that's where that encapsulation comes into place if you if you can abstract encapsulate you know data access for instance and then it's way easier to change later you can make a decision and it really does clear up you know I had a human psychological level it does clear up a lot of head space and you know in your mind you don't let you know that hey look I'm implementing let's say SQLite maybe it's the first time you've ever used SQLite you're not sure if you're doing it correctly whatever the case may be it clears up that head space because you know later on look maybe I'll learn later maybe I'll figure it out maybe I'll change it later but the fact is you can instead of you know implicit explicit lis littering your code with save statements where later on you're gonna have to go search and hunt in your code to figure out okay look I in this section I I save it to an SQLite I did this in like ten other pieces of code and now I need to add encryption or now I want to change it to CSV cuz I don't understand SQLite being able to encapsulations of your code away it's just gonna it's just gonna make it easier to work on that codebase because you're gonna have that implicit understanding at that you can change it later way easier than if you had litterateur throughout your code which is it's something interesting that I I deal with you know my day job there's you know I work on legacy code so you know there is this perception amongst other developers on the team that oh hey we don't touch that section of the app because you know I was written ten years ago and it's look at that good that code is garbage or you know it's my responsibility to fix it if it goes wrong exactly exactly and you know what if ten years ago the person who had written that code had just written it's solid and clean then we would have looked at that code and we would ah we would have been able to say listen I may not understand exactly what it's doing but I get the business requirements or in the case of being a game developer I understand what the game mechanic is trying to do or accomplish in that case it's way easier to go back and revisit that code and you don't feel bad about it and I know that sounds silly but man when you work on code that you feel bad about or you feel you know you don't feel confident about that really does have a negative effect on your ability to be productive yeah if there's something worse than when you lie to yourself to you work on a piece of code and you're like look I'm in a hurry I'll come back to this later I'll refactor it so it looks good does this little voice the back your head saying you're never coming back to this code I know this you know with this even as you write it but you're saying I don't know I'm in a hurry I can't really afford to and so writing code that you can at least kind of be comfortable coming back to later and saying okay I didn't I didn't make this impossible for myself to fix later it's usually a good good approach you know yeah yeah definitely one of the comments actually here to expand on that is there's a question here about the difference between or the preference about when to use interfaces versus abstract classes mm-hmm and I don't even get too too far into the weeds on this one either this is quite a long topic but suffice it to say interface as you understand it as a.net developer is kind of a made-up concept now everything's a made-up concept but specifically interfaces because interface is designed to solve the a deadly triangle I may have look I may have covered this before but the point of interphase is to stop this particular problem that can occur where you've got two classes that extend from interfaces that have properties with the same name or they'll collide and you can't pick which one and they have a circular dependency so interface as a keyword is just specifically drivers solution to how to handle this particular the diamond problem and because of that diamond problem out triangle and it was inherited than by C sharp which is basically aping Java so when the question becomes should you use interfaces or abstract classes I want to be really clear here interfaces don't mean anything and if you read programming books if you read any programming book the the Banga for one or anything else most people are not always working in talking net and they're not working in Java so they don't mean interface the way you mean interface when you see interface written in a programming book they do not mean literally an interface object in dotnet they usually talk about abstraction as an abstract concept can be an abstract class so there's no discernible difference in in terms of of what the point of it is any abstraction is from a technical standpoint if the abstraction you need it's the whole point is it separates out the concrete implementation from the contract you're doing now to get more specific on to.net interfaces versus abstract classes there is technically no difference until you start putting implementation details into your abstract classes if you start putting implementation details in the only reason that's a worry is you start dealing with inheritance over composition you start ending up with a point where you could have abstract classes and Heretic from abstract classes and you start meriting the million things but you can see if you press f12 in your editor of choice on the word monobehaviour and see the millions of lines of code you're inheriting and then press f12 again to go down from monobehaviour to component and see the other million of lines you're inheriting and then go down from there to unity dot object and see the other million of lines you take and go on on and on forever so that's that's why you should probably favor interfaces over abstract classes so that you don't accidentally inherit the kitchen sink that you don't need but at a philosophical level they're the same thing the point is you put in something which represents a sort of ideal contract to get you from the collaboration from what you have to what you need to do so if I'm making a game where I need to save user data and I need to I have a I have a chest I've unlocked and I have items in it and I want to save it if I have an interface called chest saver and I put it in and I save the chest I'm done my app straight to the mother wears it that's an abstract class or an interface it just does the thing magic happens and I can decide later what happens in that instance so it doesn't matter which one you pick mmm we'll find in most cases that interface will be better because you can have multiple parents so you could have mobile interfaces on the same object so it's probably better to have an interface but it doesn't matter I really want to stress that don't worry about the fact that it's one of the other again people get very much in the weeds saying you shouldn't use an abstract class here it's correct to use an interface instead no don't we ask why like what why do people say that well because again multiple inheritance is usually better and because you don't you don't worry of inheriting too many things and whatever but again it's not that important you know yeah yeah and also with abstract classes there are certain cases like patterns like the template pattern where it's useful basically what that is is you define a an abstract class with like a couple of abstract methods that need to be called in a particular order and when you create what's called a template method that you cannot override but it basically calls those classes in the particular order and you know I I can't say I've ever used that in game development I have used it in business situations businesses situation if it's not so dumb I'm a businessman now I've use her in business use cases like I'm trying to think of the case that I used it and I used it in an integration piece that I wrote between a legacy system and another piece of software where I basically was responding to events and the way I responded to events was the same way every time so I created basically an abstract class that where you just implemented two or three abstract methods and then the actual class when it was called by the by the event subscriber or whatever the case was it would call him in the right order but yeah things like that yeah and then another thing that I've used actually in game development with abstract classes is a case where you have a method where you want it to have like some default functionality where it just does nothing for instance actually in the video that's coming out on Sunday I have an abstract state class that you're supposed to an derive from and if you don't override some of the methods they're basically co-routines they just yield break you know so you can override them and you can do whatever yields you want to do with your when it's called as a KO routine but if you don't want to override them it just yields break so that was just a situation where it was how it was helpful to have the abstract class by the way well i'm kersten to get to get into the semantics on this so if i have an interface i implement the interface but if i have an abstract class you don't implement the abstract class you derive from it right that's incorrect yeah well the terminology from Java is extend extend implement is what you'd use in c-sharp it's all just it's all just different flavors at the same thing I love I love um agonizing over word usage so yeah so yeah you you input you extend yeah and you actually write it out and drop it to actually write the word yeah extend yeah interesting cool one of those things where I didn't know any of this until I started looking at the etymology of these languages like a lot of a lot of languages we came to the game so late that languages just exist like a nebulous void like some developers someday was sitting there with an old boss machine and digging through it went oh look there's a new language here let me just look at see sheriff it's just fully free like it's not how it works it's not a is not an entity that's found in the wild it was built it was built to solve a task and oftentimes by developers who were either equally as flawed as you as a developer or who had specific favorites or goals or keywords they liked or things they didn't or and most languages are meant to sir previous languages so c-sharp was built as a way to basically steal the codebase of current Java developers and move them over to the dotnet ecosystem and it worked very successfully so a lot of its decisions aren't even real decisions made by Microsoft initially they were made to make sure the Java developers were comfortable with the way the code looked the way it worked the weight function and then they added some nice sugar on top of it to make they're a little bit nicer than for the else's so a lot of this stuff when people take it for possible or granted or they kind of look at other languages and say well my language is better it's got these features they're sort of missing the point that each of these languages were built one on top of another to either do the same jobs or to steal jobs from the other or whatever else and so what's more important is to learn the philosophy behind these decisions than it is to just literally memorize the keywords and write the right ones and so a lot of these rants I'll go on about these topics really boils down to the kinds of questions people ask are far too specific like there's just there's no point in asking the question like should I use X here in this Y scenario yeah because that means you're missing two or three steps prior to that saying when should I use this and what problems does it solve you know yeah so and I think that yes you can implement interfaces interfaces can't implement other interfaces that's not a problem you can do that but ask yourself what that says and that usually means the whole point of an interface is that you can have multiple inheritance that multiple things can inherit from the same object so you can have a button that's an IEEE pressable and also I colorable and you could theoretically make an eye button interface that has both but unless you're making 50 different buttons it's kind of redundant because you're sort of missing the point of having the two separate interfaces that can be stacked in different places so there doesn't really add much value to just have an interface that wraps other interfaces unless that's a case where you might use the abstract base class to add some basic functionality but there's very rarely a case where interfaces inheriting other interfaces make sense yep all right so I think we've got thirty minutes left I try I'm gonna try to keep this to an hour and a half so let's pop into the code review before we do that though be sure to hit that like button I see 55 concurrent viewers and only 37 likes what's up with that alright so we're gonna pop over some code just read that there's a very good question here I think it's really important that oh yeah let's do it one of the questions is about a disposable mmm went when to use it and when there's a method dispose get called until the object instance have to be created in the using statement so hmm to answer this question interfaces only mark something as having a feature available to it so if you add I disposable to a class it doesn't do anything out of it out of the case it has no features you've done nothing it's just added an interface what you do though is by marking it as disposable it can be used inside of a using statement so it's not that it can only be used there it just adds the dispose method that can then be called by any script that wants to call it the reason you would implement a disposable is so that you can say this class has resources which needs to be disposed so you use it when you create something which would do something like open a file open a stream connect to a web socket connect to a database you would use it specifically to say be careful this class will need to at some point be disposed and then you just let it let it loose to the rest of the world and other people can use your code and then if they decide to they can instantiate it and call doc dispose whenever they want to it's up to them depends on how long they want to keep your your class alive for is it like so a life cycle or it can also be used in a using statement because that's just very clean way to say syntactic sugar it is just syntactic sugar that's all it really is so yeah the disposable interfaces they're not magic they look really cool but they're not really magic they're just a thing that says this has resources that will need to be closed out eventually and by adding the dispose interface you're allowing other classes to be aware of that and to sort of hook into it in certain cases that's actually a great segue because in the code we reviewed today there actually is a stream reader that is not only disposed yeah yeah yeah I mean you could actually just do er reader dot STR eat or dispose if you wanted to call that because this shroom reader has again open resources that need to be disposed doesn't closed out but in this case why don't we refactor it I'm surprised that what's it called writer doesn't have doesn't can't tell me as a tell sense to to you do using well when would it know when to stop so I guess you got a good point well what it does have is you can do a surround with yeah and uh let's think using should be in there maybe yeah there it is you can say using and that we're just gonna put in the that's another good point to write is so see that line you've got there you've got your stream reader eatery was newsreader so this is an example of what we're thinking for but the VAR keyword just write those two lines we've written stream leader or some variant of it one two three four times you can replace all of that by just in the using statement writing bar str reader equals and then using the new for that you can move all of that inside the using statement and i'm sorry i am i'm verbose with everything i write some i'm not gonna I'm never gonna abbreviate anything that's just my personal you know taste there and honestly we could probably just drop that into exactly right like in line it exactly yeah I mean if you look at it we're not using stream reader anywhere else it doesn't really it doesn't really save us anything you know in readability I think that's the most important thing and readability doesn't really save us anything so might as well just do a one-liner hang on a second that's that's now creating a new stream reader in every line on fifty that's weird what happened up there look at mine fifty something went wrong there fifty oops what the heck I've been there let me pull back oh I think Oh Oh cuz you have to do VAR stream reader right is that the syntax allow you to put the entire yeah equals new yet but the whole thing inside of these I did it is is that valid yeah that's not okay yeah okay yeah because we want to reference a stream reader inside of the thing at this point I don't know what you think about this I would draw I just renamed this reader yeah I don't know I guess at this point it really just depends on what uh what your preferences so we got our reader here now at the end of this this statement after it gets to the final line it's gonna dispose of that stream reader yeah so effectively that using block is exactly the same as if we hadn't had it and we just written reader dot dispose at the end I mean the only thing I might do is take this and put the path maybe as like something you pass into this method but where I'm not gonna get too crazy about it just yet cuz we don't even know what this code does we know it reads any CSV mm-hmm and okay yeah so we kind of dived in there let's scroll up a little bit I mean I did not we did look full disclosure Jason I did look at this code briefly and I mean if anyone can't see the code smell here you should not be numbering your variable names and you should not be numbering where is it your method names that is a clear code smell I mean this is it's code you know it's programming the computer can iterate over tens of thousands of objects you know so five objects you know that you got to think there's got to be a way to go ahead and and encapsulate this so that you're only calling rank and maybe passing in the index which is probably what's happening here and and if you're looking for a rule that gets you there but I find a lot of stuff is like if someone gives you advice saying don't write out rank one two three four why why not and someone could say well you know I can just add more what I need to the answer to why is this bad isn't just because it's a codes man and we recognize it as bad code the specific answer is if you follow the solid principles one of them is the code should be open for extension but closed for modification and in this case would have to open the file and write in more lines to modify what it does so that that is your reason why it's a bad thing to do because every time you want to add any new feature you're gonna have to completely rewrite this file and by the looks of it two or three different places so if you can find a way to take out the bit that repeats you're gonna save yourself all of that repetition yeah yeah definitely and and you look at the methods if you just eyeball them the only thing that's I mean there's nothing that's different even though these have a debug dialog statement and this one doesn't really the only thing that's different is this index here otherwise we can see that whatever they scope whatever this is doing because you know naming conventions or naming is another thing we can talk about here but whatever these functions are doing at least we know that the only difference is this this is this index and so we can refactor that really quickly why don't we go ahead and do it stew uh-oh first I'm going to take this for call this something like rank index probably could use some fancy refactoring for that but then we're just gonna do extract method I'm just gonna call this rank cuz I'm not sure what it does and now what we can do is I mean if you wanted to do a soft refactor you could go through each one of these you know and call it but I think what we're gonna really do is come up to this method over here and we're gonna just call rank and pass in ranks one through actually we just do a loop right for loop yeah it's gonna say like that you can just loop it right here yeah so we'll do 0 2 5 5 and we'll just call rank I and delete all this and switch this to var cuz we all know that's an in there you go look look at that oh hey mean that's the real lead all of the rank functions yeah so they're all grayed out as you can see because they're not being used yes that's a good point these are all gray it's very clear to me that none of these are being used so kill them fire and now we've lost like 20 lines of code that made this extremely hard to read I mean honestly if we look at rank I'm still not really sure what it's doing but hey we've taken a step in the right direction one other thing just as a small note if he scroll up to the top there yeah all the way yep so here's a little thing if you're so you know he's now migrated over from using its original UI text using text much pro and so there's a lot of nuance to using tex-mex pro that people haven't really gotten read around yet and one of the common ones is we talked before about abstract base classes just to show you this if you f12 on text much Pro you GUI I'm gonna control click see if it works wait big it froze all right fine have 12 hello oh sorry f12 I don't know my F my f12 is maps differently what are you trying to go into the file yeah just just go dead drill down into the okay yeah there we go yeah a partial class that's gonna make these confusing yeah either way I think it gave me a little think it gave me both let me click the other one is it here we go so I want a highlight here text my pro you do I is a TMP on a square text now why is that important because there's another type of text match Pro which is a world space text mesh so if you use that before you can drop a 3d text into the scene or you can make a UI text and place it on your UI as far as you're concerned it shouldn't matter which one you pick right you should have the freedom to change between a world space 1 or a UI one without your code really caring if you write text micro you GUI in your code you're explicitly saying this script only ever works with you GUI it only works with UI ones will not work with world space ones if you use the base class they both derive from you can still set the text and access 90% of the same features but you can have access to both so just as a small recommendation I would say change all of those just EMP underscore text someone asked how to how to submit code for review and how you can do that is by going to infallible code comm slash code - review or if you want drop them on the discord server trying to remember what the command is to select multiple lines at once because I want to I want to edit all these but I guess I can just do a file I hold alt and then drag a rectangle around them all oh here we go okay how's wondering what it was huh better get them all you know it screws me up I have them on so that always VIMS last your own fault gotta stop using them I'll just do a find a replace so we're gonna just change those to what was it TMP underscore touch yeah there you go and functioning that's the same thing it just now gives you the freedom of using either of them very nice very good all right cool so that's better okay so I see we've got the same issue we had before with these the numbering of these putting an index explicitly into the name of the variable let's see where these are you let's see if we can get those next looks like the only place they get used is in this show rank players function so I guess we can just convert them to lists right yep cool wonder what happened there I wonder why he opted to to explicitly name them one through five I'm gonna I guess if the requirement was I need five sometimes it can seem like an easier approach to just write the five you need that's fair oh that's fair but in this particular case it's a pretty hard thing to refactor if you're using individual variables did you ever think you'll need more than one make a list first use that and gonna grow it or change it as you need to yeah source initialize these it's a good point as well because there's a base class it's not even gonna be serialized so all of your existing references that are drag it into the inspector will stay there that's part of the same base class Oh interesting cool all right so now we're gonna do the same thing as before I feel like you know like you said if if there's only five and we know there's only gonna be five I feel like that could be maybe a Const moving forward mmm so we're gonna do text player names I dot text okay that handles all these guys and the other kind of painful thing about this sort of a factor is that I think you just mentioned sorry if i if you just mention it right now with that yeah you have to go in there and reset that right yeah I wouldn't even bother with two loops you can use the same loop for both Oh what am i doing yeah you're right keep me honest man you guys don't know what it's like to stream in code well maybe Tron does and you you've done some streaming so you know I have but I I'm not very comfortable coding live that's why everyone's wondering why you're not seeing very many scenarios with me doing the coding on stream is harder than it looks folks but I think we got it except for what's going on here what are a player points isn't a string I forgot what there didn't ya the last one is points so it's an introductory cast at the string let me ask you if what you prefer you prefer to string or would you prefer doing a string interpolation yeah to string because string and to be honest um I'd much as I really like string interpolation if I'm not literally combining multiple fields I don't really use this and also there's another whole whole of the topic if you're doing a lot of string work if you're basically combining a lot of values into one you shouldn't be using string interpolation at all you could be using a stringbuilder there's a class called a string builder which which literally takes all of your values adds it together and builds one string and it's far more efficient it's far more efficient for adding stuff it allocates less it's just a better object all around if you're just adding two or three things to make a print fine no real issue what they're doing if you're actually working with CSVs and doing complicated stuff like this look into the string builder class that's what you should be using for a lot of text work yeah that's funny I we're doing some what does it called mob programming here because I saw some good some good advice from the chat obviously one of them is I think the player names and player points that needs to be some sort of struct and also a good point is that we could just do player names dot like for each write and then just do for each one oh no you need the index no gene either I think it could be only the index for this yeah in any case you know what's interesting to I I was saying that maybe I would say though one thing is well to be careful of with the for each actually might be fine as does the new version it used to be an issue in unity anyway if you're using for each it works on lists and that's not a native type you're using for it works on a raise and it basically uses the C++ arrays you're not actually creating a list like you would be a fusing c-sharp so in any scenario where you can use it an array it's actually really interesting if you D compile your code and actually look at the operations you can literally see there's like twenty percent less operations if you're sticking with integers you're sticking with arrays rather than using lists because you're not boxing it to a list type hmm so usually I stick with lists even if I stick with arrays even if I could be used a foreach loop I would just iterate using a for loop with the theory gotcha not always the case just sometimes mm-hmm yeah I sign your points out it creates garbage that's what I was getting a for each ooh garbage because what happens is like I said for each works so if you remember what I said about post right if you make something I disposable it doesn't do any magic it just marks your file as being capable of being disposed and the same thing is true for ienumerable if you mark your class as ienumerable it doesn't do anything special it just says this class is capable of being iterated through so any class you make that extends ienumerable can be put in a for loop before before youtube that's kind of the point of it it lets you do for each blah in my class so if you made your own thing called house and you wanted to have a way to iterate through all the rooms you literally make an ienumerable that iterates all the rooms in the house and you could just write or each room in house like you could do that as a really kind of nice syntax to write hmm but in this case to do that you have to cast to the ienumerable type and to do that you're gonna end up getting these scenarios where garbage will be generated back and forth so yeah if you have a set number of items and you know what you're doing you can stick with an array so if you ever look at code which does stuff like mesh generation they're not gonna use lists in most of the case it's gonna use arrays because if you know specifically how much memory you're allocating you can just make an array of 12 and then iterate through your array and there's no other boxing be done yeah so I see here I was looking to this as you were talking trying to make sense of it and I think the yes we have five kind of littered throughout here so you're thinking that you're probably thinking yeah maybe there's only five and it should be you know maybe this class should be called top five ranking or something but then I see this this rank variable which really should be called ranks it's a list of strings and I think the number of ranks is dictated by how many ranks are added via the the editor you get what I'm saying like maybe there's platinum gold silver those are the ranks is that you does that make sense I mean I loved so yeah let me go back up here I think there's a disconnect because there was that whole rank 1 Rank 2 ring 3 up to 5 and so now I'm thinking maybe we turn this 5 into a constant saying that's how many that's that's the best word looking at there's the top five people or the top or whatever yeah but then I noticed that there was this one list here called ring what you're saying is that's meant that's meant to dictate the number of ranks in the system yeah like maybe their names rings the ranks dot length as opposed to five so just saying exactly like maybe if you were to go and look in the in the editor before we tore this up this would have literally five strings that represented five different ranks and then he went ahead and said hey you know I got I got five or eight you know I got five ranks here in the editor why don't I go and just put five methods in to handle them and there's that sort of disconnect there mmm you know I'm saying I'm not a hundred percent sure though I guess - in order to follow that theory we'd have to take a look at how rank is used and I see here show rankings I'm just gonna ignore what these clears are cuz I don't know what's happening but show rankings actually loops through ranks whatever ranks is and then it does a split now I'm confused actually maybe I'm totally wrong about that what is it splitting what is what is it almost looks like ranks it's supposed to be something that comes from the CSV file now that I look at it yeah I'm not entirely sure I noticed the CSV file didn't mention anything to do with rank name so that's a bit dubious about that idea well actually look at the rank method the rank method is what adds to rank well true true but you know did get it was derived from actual logic that was he was that he added here so he's saying look so for rank one which whatever was hard-coded he loops through data values looks for something and then adds that data value to the ranks this is a tough one well let's let's just take a quick detour cuz it's not this code but it's highlighted a few points I want to cover that'll come up in the chat okay let's do it because this is kind of hard so one of them let's just screw up at the top where we have our list object okay okay so somebody asked the question when should you use doctor list and is that performant is that costly well here's something I want to really I really want to I think it's worth doing a deep dive now and what that actually means so we're gonna go a little bit crazy here I might actually recommend make an empty class for this to cover this because I think this is a very big topic look at it so let's make a nice simple class we're gonna call it well just collection test simple example yep so this to a to another file so it's okay so what I'm gonna do is just make a array of strings just call it strings mm-hmm and make a list of ins yeah and last but not least make a ienumerable what's bothering me story that's right alright and we're gonna say it's gonna be of whatever your floats do I know all the floats oh yeah yeah so we're gonna deep dive into what the difference is between these in terms of specifically when it comes to the concept of a new more ability so make a constructor there mm-hmm CTU ARMA and you can just CTR and I'm gonna do it I gotta learn CTR I knew that have a whole video matically I have a whole video on that oh but I want to highlight here is horizontal I want first of all point out if you write underscore strings dot mm-hmm I just have a look at our list of available options there's just kind of press down through some of these or whatever you'll notice there's one there called get a numerator yep which will return this as I might do this there it is yep and that's about it everything else here looks fairly standard list related stuff now do the same thing with the integers 1 and let's look at what options are available to us here and if you go down through good all those a lot of stuff to do with lists yeah but we should notice a very few and your friend here another one get a numerator mm-hmm so he's there as well and the actual the float one is also an enumerator well it'll do the same thing it'll give you this well this one yeah so whatever so now here's but you notice that has nothing else right the entire ball is nothing else but in a waiter so now we'll actually look at what they do so he dives into the eye anymore a ball object there Oh like ya got to go down with the class deklerk so what is an ienumerable it is a thing which returns I get a numerator that's all it does doesn't do anything else except gives you in a numerator of itself and in this case this is an out parameter version so it returns at whatever the type is it's for genero sizing it if you just go down one more level into high and wearable that the generic one that just doesn't have a parameter it's exactly the same thing so the first thing to note here is ienumerable all it does is return 9 a numerator of whatever it is now let's have a look at what ienumerator is so I go back 1 and dive into what the I numerator object is yeah hmm what this is a thing that has a parameter called current that's all it is and it's disposable which is a separate issue discussed earlier but it just has a current object and if you go down into the next one down into I enumerator it's a little bit more complicated it's gotten current move next and reset that's that that's the mean potatoes right there that's that's the heart right there so what is an enumerator it is the thing that can be stepped through until there's no more left so keep that in mind forget about everything you know about lists and arrays and collections where else what is an enumerator this is a thing that has a number of steps a current one defective number of steps and then eventually it has no more steps and you can reset it if you need to that's all it does so can you now see how co-routine is just a number of steps of work to be done that can be run across multiple frames or lists just number of steps of things that you step through one by one so with that in mind if we head all the way back to our actual class or working on that one we did this one this was fine so from here you can now see you've got your your various different ways to transmit enumerator and because of that each one of these can be used in a for each loop because what's the for each loop do well it looks for an object that can return in a numerator and gets the numerator so those for each functions and using a for each loop all three of those can be used inside of a for each loop so just to prove how this works if you go to list you'll see it's the same thing it it's ienumerable so you'll see this is a lot of stuff attached to it Wow and if you're wondering what the specifics are ienumerable lets you iterate through something a collection is an object that lets you add and remove items to it that's all it does and a list is an item it's a list that can be added and removed too but also be accessed by index so the question of could you have multiple interfaces implemented further who in earlier yes you could which feed to the point in this case a list is a thing that can one be iterated through to you return this read-only three add and remove a collection of items and four be accessed by specific index numbers so each one of those interfaces promises a whole different subset of things that a thing can do so with all of that being said when you return something as an enumerator and just prove this so head back to our method were working on mm-hmm this is kind of funky syntax people might have seen before make it function and it'll return a so we're gonna return a ienumerable and call it get numbers and I just want to do F to a for loop here between one at zero and ten and inside that inside of the line 18 just write yield return I that is a particularly weird piece of code and what it does is it returned in enumerable collection of numbers but this this will now get to the point of what an enumerator is you can for each through and it'll return all the numbers and that's that is now a thing that can be enumerated because in innumerable returns numerator but this is the bit I want to really really focus on when people ask these two string coder is to string bad right var numbers equals get numbers yeah now so that numbers variable has not been evaluated yet it is a thing that can be enumerated over at some time but hasn't been yet and doesn't exist in memory as a collection of objects so what you can do is when you're finished adding to it so you could say for example at the end of that money to use the import using system not linked I think oh yeah link yeah so now at the end of that get numbers you can write dot order by or sort or whatever else any other one you want and then x equals x bit silly but yeah there is the wrong one yeah we don't have a type they'll have to cast it yeah we change change ienumerable to be nine or more blobby and so that would that that'll work then Oh true that's using the base version I get it right but this may seem weird what we've done here what we're saying is that enumerable collection of numbers get the numbers then order if you got to order by descending as well as on the one just right order there's there's lots of variants or actually no you know what right take take two alright dot take two that's probably simpler I wanted to get a sense of yeah thank you so what does that do that says here is an enumerable collection of something yeah go through that collection only take two of them so what we've done is that's not evaluated yet that's just a promise to doing a bunch of stuff and at some point we'll we'll squash all of those commands together and be left with a list or an array and the way you do that is the next line where that's where it gets important your right numbers dot two lists mm-hmm so the question of is to list costly well two lists is literally when you're evaluating the equation from before now this gets really important because if you write ienumerable it doesn't evaluate yet and this can lead to errors where you pass a numerable through your code it throw an exception until the moment you write to list yep so that was a really big roundabout way I was saying ie numerators are a type of thing that is a promise to evaluate at some point into a collection of items it's a design pattern it's called the numerator pattern and it's designed for this exact purpose I've been able to pass things around and perform multiple operations on it the best example of this will be something called linq to SQL and that means you can actually connect to a database and say these ten items what you can actually do is you can stack things get me that these 10 items where the name begins with s and the date of birth is greater than whatever day you can you can make a query that extends and then when you're done evaluated into can array your list and by the way you can write to array instead of two lists if that's what you want so this is the reason I'm going through this great length for this is to really highlight the fact that an enumerator isn't a list people really mistake the fact that the an enumerator is the list of out it is not a list of items it is a promise to go through a collection of stuff and eventually end up with a list of items and this is when that happens when you explicitly a casted or call to list yeah now this is where things get really interesting imagine just as that just as an example go to line 21 and write int number right now after I hear I sorry I know after I on 28 oh right no it's right that the one on 28 oh yeah right plus I plus number plus plus now this is really weird I don't know what I'm doing all I'm saying is that return the numbers 1 to 10 and add nothing to it the next time I'd want do it the next time add 2 to it and that number will increase every time you iterate through that code the reason that's important is on the next line after 17 do a for each Oh 17 sorry and iterate through numbers yeah now here's the thing if we were to print on line 14 and we were to print on line 20 the value of numbers is different yep and this is something I really really want to stress here this is what I mean about it not being an array it is something as being evaluated as you call it which means the fact that you can run the same loop in the same frame the same function and it can be drastically different really sort of demonstrates the fact that there for a certain purpose they are for stepping through a collection of things they are not for doing any sort of heavy lifting logic and that's why if we roll all the way up to the top again you'll get this error this message well if it says it specifically here if you I think I mean if you go to line 22 and iterate through numbers again the second time oh yeah I think I saw it earlier my name Lu just right for each in numbers yeah you'll get a little warning see that little blue line yeah I can't read it here it's as possible multiple enumeration what's not telling you is be careful you are possibly numerating through this collection multiple times did you really mean to evaluate the answer to what it is is a list and then step through it multiple times because that is a very different statement then evaluate the list it had not happened when I did this I when I said was it oh yeah when I said sorry list I went numbers to list and then right after that I was like oh let and this is probably something that's common that maybe be like oh I want to save it as a list twice or I want to store it in two different places or something like that it's gonna go through it and the next time it rolls through this is gonna be a much higher number and a much different list exactly point of this is that you steps why when you're given something in an ienumerable format you're always suggested to cash it into a list first before you start doing all of your operations on it so there is surprisingly a lot more to say on this topic and I don't want to go crazy because this should already be a lot of information so if you enjoyed that explanation please hit that like button I just I just want to make sure that people realize interfaces aren't magic there's something that promises features they say I am capable of performing this task so a disposable is capable of being disposed and innumerable it's capable of being iterated over that's all it says you have to implement it you to do different stuff with it but that's sort of the general point and in this case you can't trust the numerals because the point of an enumerable is to say this will some stage be some data so how do you think this informs co-routines to bring it to rain it all the way back to to unity yeah okay that's a very good point so the thing is this actually highlights a very good in a very interesting point you brought up actually so create a method it takes in a core team call it run synchronously my gosh I just misspelled synchronously don't hate it all right you know I didn't writer sorry it's Jenna taking a night enumerator I'll change it a second all right and then call it a routine I love this is a function that theoretically takes in a Co routine right now just write a while loop mm-hmm all right Cora teen dot move next yeah and then I'm yeah and you can say for routine current and you could theoretically interact with the object there but here's the fun thing if you just delete that line there believe that the current bit congratulations you've already you've built your own handler for Co routine that's what you know routines are they just iterate through the different steps in front you get almost all this start co-routine you could but here is the difference this is running all in the same right cuz it's sync right so all that all that the Ronco routine really does is it takes an enumerator and says rather than saying while I'll do it all in one go it says new part of it waistline x-frame you part of it it'll next frame do part of a riddle a nice room so this is water Carver Dean is it is the series of steps built in these little incremental pieces and just to show we can actually do this if you look at that get numbers if you look at it that is a core routine so for example we could make a function there called Mike or tea it's a returns item where I will just do the classic thing of saying print alone yield return you wait 4 seconds Brenda line I should probably this Amano behavior yeah whatever and he'll return mm-hmm so this is sort of a bargain-basement standard core routine right don't do some work wait if he's that gonna do some work well we could theoretically run this we could call run synchronously and pass in micro routine and we've now built a way of running our synchronous our routine in a synchronous way so do that say after line twice yeah go so that's all that Tina doing they're not magic and this is why I say when people say wait go routines aren't asynchronous know this they're literally just a stepping through the stages of running a chunk of code and there's there's some invisible magic to have this stuff worked but it effectively boils down to here's where we get a bit meta f12 on wait for seconds sorry after I say f12 but you know what I mean yeah I know true so this is what's called a yield instruction and go down one last well I think it should be one more after that I think no okay no it does no more but either way yield instruction does effectively work in the same way from an enumerator standpoint that it iterates you can close out it doesn't have to pay I was hoping yeah yeah yeah I was gonna see fortunate but I guess the point is that new writers are yield a bowl which basically means they can be waited for and so that's what that's what all the the magic is with the yieldco deal key word but where this gets interesting is because an enumerator has a bunch of steps to it that basically iterate through you can yield return another code retain and what that's going to do is it's gonna iterate through those steps and do more so again there's no magic to this this is what's really cool if you start to break down through all the different stages it's doing the same code you could have written it's just doing it in a way which is stitched together for kind of more complex architecture 12 that was great I didn't mean to go down that long at their whole routines I dunno I that was good I didn't want to enter over at the time I didn't want to interrupt cuz it was too good that was great that's what happens when jason has like three or four beers just we go deep into the and to the depths of the language alright well I think we did it you know we kind of got through this a little bit to this review and we did fix some stuff up it was a little confusing and I think it kind of falls outside of the scope of we're still kind of learning what works for these code reviews but this one was kind of hard to follow so maybe we can revisit it later on after I've taken some time to look at it it'd be probably too boring to watch us sit here for five minutes staring at the screen with blank expressions on our faces for the sake of the next stream is we'll we'll refactor this one show a side by side and we'll go over why we made some decisions we did that might be a good compromise that's a good that's a good idea and I want to thank lucky so for allowing us to take a look at your code for submitting that I appreciate it you're the first one to use the the code review form so if you go to infallible code comm slash code - review you can submit your code as well again thank you man appreciate it and you know we'll try to refactor this over the course of the next couple days and in the next stream we'll we'll try to show you a before and after speaking of the next stream this is gonna be a weekly thing and so far I think Wednesday's have been very good I still not sure it might be Tuesday's though so just keep an eye out for that I've got a video coming out on Sunday so mark your calendars or whatever you do you want to remind you that there's a video coming out or I would say also was on the side because as you can see we tend to get sidetracked a lot often random topics if there's a question you want asked when it doesn't don't have time for it and these kind of you know scenarios feel free to write the questions in the discord and the benefit of doing that is it gives us a chance to have a look at it and try to figure out how to maybe have some visual representation in advance yeah because this is sort of seat-of-the-pants and it might have been a bit hard to follow and I fully understand we covered a lot of sort of nitty-gritty of how both c-sharp and unity works here if we have some of the questions pre-prepared we can maybe prepare some code that might be easier to follow for these kinds of more complex topics so if there's a if there's a question like how does the magic void start function work in unity why does why does it happen to get called even though it's private if you got a question like that you can ask us we can kind of come up with a good way to demonstrate how that works and then we'll cover it on on the next review and then we'll formalize it and turn it into a video so there you go that's the process of making a youtube video folks when's the course that's funny that someone would bring that up cuz well I won't say anything anyway thank you for for coming guys again weekly so keep an eye out for next week we'll do it again put your code through a code review and drop your questions into score and we'll try to pick some that we can maybe prepare some more formal explanations for anything else no I think that's it I think that was a I'm I almost think we cover too much is there such a thing oh speaking of covering too much if you couldn't stick around for the whole stream you're probably not here and right now so you're not hearing me say this but I'm gonna cut this up into clips that's something I've been trying to do so make sure you um check those clips out and even if you already caught the stream it would be so helpful as if you would go through those clips and like them when you see them maybe even leave a comment it just really helps it just shows that you know that you appreciate the content and it lets us know what kind of content to make and what kind of things to cover because this is only our fifth stream and we're kind of still you know haven't taken the training wheels off but as I make a point as well is that I go through the clip mmm because they're more bite-sized and for easy for people sort of hone in on a point and if people write questions directly on underneath those videos about what's covered in the clip I'll usually respond that's actually a good point if there's a question that you couldn't you didn't get answered you know look out for the clip and and see if you can try to drop it there and we'll get to it so alright well thank you all have a good Wednesday and we'll catch you next week all right look later
Info
Channel: Infallible Code
Views: 2,021
Rating: 5 out of 5
Keywords: unity 3d, gamedev, game dev, unity3d game development, unity game development, unity 2019, unity3d, unity, how to make games, unity game dev, game development, indie gamedev, how to make a game, game programming, game developer, game development unity, c#, unity 2018, programming, games
Id: MeG9Yg1cCB8
Channel Id: undefined
Length: 107min 49sec (6469 seconds)
Published: Wed Dec 11 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.