Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Question What are the most important data, method and structure types besides the most basic ones?

Discussion in 'Scripting' started by InacioM, Jul 9, 2020.

  1. InacioM

    InacioM

    Joined:
    Jun 19, 2019
    Posts:
    36
    Hi, everyone

    I realize I'm asking many questions, but a simple push in the right direction would be very appreciated. I'm most interested in real application (either actual application or just examples of applications) of those techniques, instead of just definition or example code

    I'm a fairly new developer, but I've done quite a few courses so far.

    However, all beginner courses I've seen only deal with the most basic stuff, building programs with them alone, barely touching other techniques.

    While that might be a valid way of programming, I think it's probably not best practice, especially when performance is to be considered.

    Besides ints, strings, floats and bools (and Lists or arrays with them), what are the other most important data types? When should I use them? Should I use Tuples? When?

    Also, what about structure types? Besides classes (simple, static, and inheriting mono behaviour), what are the other important structures? Should I use abstract classes? When? Structs? What about actions and delegates? Are there any other structure types I should be aware of?

    And methods, should I use extension methods? Why? Override methods? Any other?

    I'm also aware that I shouldn't use something just because it exists, but that is exactly what I'm concerned about: when exactly should I use them?
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,060
    Learning is the modification of behavior as a result of experience.

    That means you need to experience game engineering in Unity3D in order to learn it.

    There simply is no other way. Reading about it will help, but it's nowhere near as useful without the simultaneous experience. Do the thing you want to learn.

    Go out and work through Youtube tutorials such as what's on Unity's site, or else people like Brackeys or Ray Wenderlich. Just put your entire focus into one short tutorial and say "I'm gonna make and understand everything about this little tutorial," and try it out. Don't race, just work through it. Back up as much as you need to.

    If you get stuck on one, move to another, but try to finish at least a small one, and by finish, I mean have some workable mental model of all the pieces involved, a model you could explain to your dog if you had to.

    See me in the image? I'm explaining how Unity uses colliders to my dog in that particular shot. My dog still thinks I'm an idiot, but I know how colliders work in Unity.

    Once you do that, the next tutorial is easier, easier, easier, and that lets you do more complicated things. Before long you'll be amazed with your skill stack.
     
    PraetorBlue and InacioM like this.
  3. InacioM

    InacioM

    Joined:
    Jun 19, 2019
    Posts:
    36
    That was incredibly well put.

    In fact, that's what I'm doing. I've just finished Catlike's 27 part tutorial on a Hex Map Editor.

    I can't say I know everything I've done, especially with shaders, but I got most of it.

    But I'm still not sure of those many different structures. Actions and delegates, for example, are not used in that tutorial.

    Do you know any course/tutorial that implements those more "advanced" data types, methods and structures?
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,060
    I actually don't, but here's the basics of what an action / delegate is: think of it as a reference to a function, possibly including arguments and context for that function. That's it.

    They are used (for instance) in asynchronous programming (like networking), where you say to the network, "Hey I am not going to wait for you, but I want you to go get me this data, and when you get it, call this function back with the data to give it to me. Bye now!" and then the code forgets about that network call. Later the network code gets the data back and says "Hey, call this function and send the data as an argument."

    There are also TONS of names for essentially the same concept: function pointer / action / delegate / callback / functor (there are LOTS of names for it, each implying subtle differences) are all semi-synonymous.

    Often with networking you give it two functions: the success function ("Here's your data!!") and the fail function ("here's the error I had, sorry.").

    Another common use is to hook up buttons and other input structure. "Hey button, when you get pressed, just call this function," and that lets you change it dynamically to another function, or let a bunch of unrelated functions all connect themselves to a single button.

    This is where it can get bewildering, as you can have multiple different functions all attached to the same delegate.

    Not only that but each one can remove itself from the list of people to be notified.
     
    InacioM likes this.
  5. InacioM

    InacioM

    Joined:
    Jun 19, 2019
    Posts:
    36
    Interesting!

    Very well explained.

    I'm atm doing the Learn's "C# survival guide" so I can understand those other concepts.

    Would you say there are structure/data/method types that I should avoid using?
     
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,060
    Everything is appropriate in its correct context.

    In Unity, there's a bunch of "bad idea" calls, such as GameObject.Find(), but even then they have a place in rapid prototyping just to shave minutes off of delivering something your boss wants to see 60 minutes from now. :)
     
    adamgolden, InacioM and PraetorBlue like this.
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,060
    Let me expand on this even further: this is software engineering. That means every single decision you make has a cost and a benefit. It's unreasonable for you to "pre-know" all this information. It's too much.

    Instead you need to learn what you need for any given task, try your best to understand the costs and benefits of that choice, try to perhaps assess alternatives, and from that you will develop the ability to more effectively make meaningful cost/benefit tradeoffs.

    If you fold a stiff piece of cardboard in half to prop your desk up so it doesn't wobble that's engineering.

    If the researcher uses a laser to ablate a few micrometers of your cornea to improve your vision, that's also engineering.

    i.e., "it's all just engineering."
     
    InacioM likes this.
  8. InacioM

    InacioM

    Joined:
    Jun 19, 2019
    Posts:
    36
    Thanks! Makes sense.

    So that's basically why we usually want to make our functions and types as independent as we can, because if later we find a better alternative, we can just alter that specific method and "everyone else" won't have a clue that it changed. Right?
     
    Kurt-Dekker likes this.
  9. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    2,000
    Extension methods are fluff. You didn't ask, but so are getter/setters. Tuple are just bad classes -- skip them (other languages have great, easy-to-use tuples, but not C#). You'll never need inheritance (which includes base classes, overrides, and virtual). If you understand in Unity
    Collider c;
    can be a BoxCollider or Capsule collider, you know plenty of inheritance. Structs are just Value Type classes (Value type vs. Reference type is a big deal in many languages now).

    Get the most of out classes and lists/arrays. You can have an array of class Robot, where Robots.explode() remotely blows up one robot. If you can carry several eggs, know you can make
    List<Egg> myEggs;
    and get comfortable adding and removing eggs as you go, or can search for 1 egg type. If you need several copies of 3 variables, know that you can make a normal class inside of a script and put it in an array. If lots of your scripts have identical stats for cake decorations, know you can make a normal CakeDecoration class and they can all use [ICODECake]Decoration CD;[/ICODE].

    The thing about C# delegates is, as KurtD writes, they're fairly basic (they were invented in the mid-50's) and useful, but C# does them awkwardly and mixes in an obsolete version and funny terms. Unity buttons allow you to plug in a "what do I do when pressed". That's technically a delegate. If you're making, say, a trap and want to be able to plug in what it does, then you might remember that "delegates" allow that, and go back and read up on them (but having
    int trapType;
    and lots of IF's will also work).

    This is for making games, even somewhat larger ones. If you want to study computer science, then learn inheritance and delegates (and also recursion). They're bread-and-button advanced concepts. The people who made Unity clearly know them.
     
    Last edited: Jul 10, 2020
    PraetorBlue likes this.
  10. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,060
    I like you more and more with every one of your posts.

    Seriously.
     
  11. InacioM

    InacioM

    Joined:
    Jun 19, 2019
    Posts:
    36
    Hey, Owen! Thanks for the tons of advices.

    I like how extension methods clean the code. Is it bad form to use them?

    I also like Properties with different get/set methods, say a bool "IsDead" that returns "true" if a field "health" is equal or less than zero. Or a "Equipped Weapon" property that calls "Refresh Stats" only if the equipped weapon change an attribute (or something like that). Is that the best way to do this kind of stuff? Or should I do it in another way?

    I'm planning to use Tuples in a specific way, which is being the Key value in a Dictionary.
    I have this big dictionary that calls values based on many different variables, kinda like
     Dictionary<(Locale, Locale, Date), Advice>
    where you say where you are, where you're going to, and when, and the dictionary has a specific advice. Is this a bad approach? Any other better way to retrieve data from a collection using multiple keys that return a specific value?
     
  12. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    39,060
    I recommend keeping your booleans "positive," as in "isAlive" instead of isDead.

    Always choose to use XYZEnabled rather than XYZDisabled, at least to the extent practical.

    I will however grant you that isDead isn't too bad, since it chimes pretty well in your brain when you read it.

    But it's always easier to glance over complex logical expressions if everything is positive.
     
    InacioM likes this.
  13. InacioM

    InacioM

    Joined:
    Jun 19, 2019
    Posts:
    36
    Makes sense to use a standard for booleans.I never thought about them this way. Nice piece of advice! Thanks again
     
  14. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    2,000
    As you wrote extension methods merely make it look a little different -- they don't do anything. No one ever got stuck making a game and thought "aha -- an extension methods will solve this".

    Plain old member functions do everything properties do, and more (they have more options for inputs). In the end, all properties do is make your code a little different looking.

    That sounds cool, except strings do the same thing: Advice["Brisby/Stanton/Tues"]="Tuesday is when the carniverous sand worms are the most active!";. Beyond that, you may not even want a dictionary. Since this is Unity, you probably have the travel advice in a list in the Inspector for each town. Maybe even for each of the roads leading out. It might be easier to read it directly from there.

    Overall the problem is how all that stuff becomes mental clutter. A game feature you could write and test in 1/2-hour now kills most of an afternoon. Every little C# "fun" feature you add makes you forget the game thing you were trying to do.
     
    InacioM likes this.
  15. Owen-Reynolds

    Owen-Reynolds

    Joined:
    Feb 15, 2012
    Posts:
    2,000
    Anymore I just write both.
    if(!e1.isAlive())
    is just enough slower to read than
    if(e1.isDead())
    to justify adding
    bool isDead() { return !isAlive(); }
    to e1's class.

    But then again, I don't even start off with either.
    if(e1==null)
    is fine at first. There's a school of thought that unless you've made the same thing a dozen times before, you never know how it will turn out, so don't waste time making your temporary code pretty.
     
    InacioM likes this.
  16. InacioM

    InacioM

    Joined:
    Jun 19, 2019
    Posts:
    36
    Thanks for the insights!