Entity Component System | Coding a 2D Game Engine in Java #10

Поділитися
Вставка
  • Опубліковано 13 тра 2024
  • Join the Discord: / discord
    In this tutorial, I describe the different methods of abstracting game logic into components. Specifically, I go over the Component Pattern as described by Bob Nystrom in GameProgrammingPatterns, data-oriented design, as specified by the article below, and Entity Component System. I give a brief overview of how each of these systems are coded, and then we implement the Component Pattern.
    I also describe how to handle the problem of Component communication. The method I use, uses the GameObject as a middleman, that coordinates communication between different components that it contains.
    Code for this tutorial: github.com/codingminecraft/Ma...
    ECS Articles
    ============
    * / entities-components-an...
    * gameprogrammingpatterns.com/co...
    I haven't looked through these articles, but it looks like there may be some good resources.
    * github.com/dbartolini/data-or...
    ---------------------------------------------------------------------
    Website: ambrosiogabe.github.io/
    Github: github.com/ambrosiogabe
    Here are some books I recommend if you want to learn about game engine development more thoroughly. I do not profit off any of these sales, these are just some books that have helped me out :)
    My Recommended Game Engine Books:
    Game Engine Architecture: www.gameenginebook.com/
    Game Physics Cookbook (Read this before the next physics book): www.amazon.com/Game-Physics-C...
    Game Physics (Ian Millington): www.amazon.com/Game-Physics-E...
    Game Programming Patterns (Free): gameprogrammingpatterns.com/
    My Recommended Beginning Game Programming Books:
    JavaScript Game Design: www.apress.com/gp/book/978143...
    My Recommended Java Books:
    Data Structures/Algorithms: www.amazon.com/Data-Structure...
    LWJGL (Free, but I haven't read this thoroughly): lwjglgamedev.gitbooks.io/3d-g...
    Outro Music: www.bensound.com/royalty-free...

КОМЕНТАРІ • 120

  • @whatunoaboutit
    @whatunoaboutit 3 роки тому +2

    Glad you chose to make this series. Very informative!

  • @herlufbaggesen
    @herlufbaggesen 3 роки тому +7

    This was really well put together! You explanation at the start was exactly what I needed to get some perspective about the different types of solutions. Thank you for making this video!

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому +2

      No problem Herluf! Thanks for watching, and I'm glad I was able to shed some light on different ways of implementing ECS :)

  • @beaumanVienna
    @beaumanVienna 2 роки тому

    Very well explained, great presentation, nicely done!

  • @BudgiePanic
    @BudgiePanic 2 роки тому +1

    These videos have been really good, rivalling actual undergrad course on software design

    • @GamesWithGabe
      @GamesWithGabe  2 роки тому

      Hey PineApple! I appreciate the comment, and most of my undergrad courses felt the subpar as well, but the textbooks that were assigned for the courses were usually very helpful :). And it also depended on the professor haha

  • @AdityaSinha92
    @AdityaSinha92 2 роки тому

    incredible explanation. Thank you!

  • @onerimeuse
    @onerimeuse Рік тому +1

    One, this is probably the best video I've seen yet on the actual structure and architecture of an ECS because it describes the "why" so well.
    And then you got to the programming bit. I was going to click off then, since I'm not advanced enough a programmer yet to watch someone program and get it usually... but you're describing the what and why in that as well. I'm only to component class, but because of your wonderful articulation of the details, I'm totally on board. Thank you for making such an awesome video!

  • @arnetriesyoutube
    @arnetriesyoutube Рік тому +1

    This was really helpfull! Also very well explained, although i don't get why people are calling you out for not using ecs instead of ec. I think you explained your reasoning very well. Oh and i'm impressed that you are taking the time to answer those comments here and give some sources where to further ones studies. I think that shows great charakter.

  • @HendrawanAdiWijaya
    @HendrawanAdiWijaya 4 роки тому +6

    Wow, finally a video about ECS! Let me craft my morning starter pack first, then i'll dive into it.

    • @GamesWithGabe
      @GamesWithGabe  4 роки тому +1

      Haha yea, I figured it was time to finally start talking about it in terms of the engine that we're making. Unfortunately it's still very similar to the last one I coded, but I try to talk about the different methods and how you might implement them :D

    • @HendrawanAdiWijaya
      @HendrawanAdiWijaya 4 роки тому +1

      Based on Component Pattern by Bob in his GameProgrammingPatterns site, he updates all components inside entity update, but he mentions this implementation is not correct in this video ua-cam.com/video/JxI3Eu5DPwE/v-deo.html :v I agree with him, components should not be updated inside entity, and components with same domain should be updated in the same loop after another domain.

    • @GamesWithGabe
      @GamesWithGabe  4 роки тому +1

      Hey Hendrawan, sorry about the late response, I don't get notified about replies :(, but I agree with you that the components with the same domain should be updated in the same loop. The reason I don't implement it that way is because this tutorial is in Java, so we have no control over where the components are being placed in memory. That means that even if we update each system (instead of each entity then all the components) it won't help much because we have no guarantee that the systems will have components placed next to each other.
      I am planning on doing some tests pretty soon in C++ to see what kind of performance gains you can achieve using his method, and I want to give a tutorial in the future about writing game engine in C++ so that we can implement these performance gains :D

    • @GamesWithGabe
      @GamesWithGabe  4 роки тому

      Hey Hendrawan, I wrote up a simple ECS benchmark test in C++. I ran the test as if a player had played a game for 30 minutes at 60 FPS, and it was a game that consisted of 10,000 entities with 4 components each. The results I got were:
      1.) If you don't use ECS, and just allocate random memory and iterate over it, you get an average of 983 microseconds to update all entities in one frame.
      2.) If you use ECS (I allocated 100mb of memory, and stored the components right next to each other, then iterated over each component and updated) you get an average of 680 microsecond to update all entities in one frame.
      I'm not happy with this result though, because a real game is way more complex and the only way to truly test this would be to build the exact same game using ECS, and not using ECS. I plan on doing a longer term test and making a video about the results in the future. Let me know if you want access to the benchmarking code I used and I can upload it to Github and send you a link :D

    • @HendrawanAdiWijaya
      @HendrawanAdiWijaya 4 роки тому

      No notification for boring comment :v I didnt even know that java behave differently than C++, i should learn more about memory in java. There are good reasons by putting each components with same domain in one system though,
      1. Order is matter when updating components, like input for movement should be placed in the first row, then physic and then graphic, with system we can make sure all components can be updated in correct order.
      2. Reducing gap between component of each entity, ex there A - Z entities, each entity has 4 components, and we update all components of one entity after another, the gap between component number 4 of entity A and entity Z is farther than if we put each components with same domain in one system. The farther the gap, the more weird will be.
      Give me the link please :D Curious about ecs in C++

  • @jestry2508
    @jestry2508 3 роки тому

    I enjoyed it once again :)

  • @davidmarinho2848
    @davidmarinho2848 3 роки тому +3

    Me when video starts:
    Finally! Something that is very familiar to me.
    Me at 1:52 of the video:
    Ok... It's better to pick my notebook.
    Hey Gabe, I am enjoying lot your tutorial series.
    I am learning many new things, not just about LWFGL, but also about new games' concepts that I have never heard talked about before (for example, in my games I usually use the first method that you talked about at the beginning of the video, at least until today, because that method of doing that seems very interesting and just better ahahah).
    And it's incredible how your half-hour of content takes me 1-2 hours.
    Please, just keep going with the series, you are making an incredible job and helping a lot of people.
    Thanks :D

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому +1

      Hey David! Thanks for the comment, I really appreciate the support and I'm glad that the content is helping you learn about new techniques. I'm also learning new game design techniques everyday and hope I can share them with you guys. I definitely don't see myself running out of video ideas anytime soon, so I should be able to keep the series going :)

    • @davidmarinho2848
      @davidmarinho2848 3 роки тому

      @@GamesWithGabe You are welcome, you deserve it!
      Nice! It's important to invest in studies almost every day and you are doing a great job in that field.
      I am also willing to see all your series xD.
      P.S.: Also enjoying a lot your geometry dash series :D.

  • @Snowmanver2
    @Snowmanver2 2 роки тому

    amazing and interesting~

  • @lmao_ur_mum
    @lmao_ur_mum 3 роки тому

    Nicely explained but my head still hurts :D

  • @luandkg
    @luandkg 4 роки тому +2

    Wow, amazing 😍 😍😍

  • @hyperocket3279
    @hyperocket3279 3 роки тому +6

    This was pretty interesting... now I understand why low level languages are soo glorified. Learned some new java stuff to :)

  • @calvinwithun6512
    @calvinwithun6512 2 місяці тому +1

    Hey! I'm loving this series so far. I tinkered a bit with LWJGL back in college in my spare time but it never really settled in my mind. This tutorial series is doing a great job of explaining how everything works under the hood along with how to actually code it into the program. Very informative stuff and I appreciate it a ton!
    One Q though, if you're still checking comments here... the 'jade' package. Is that just a name you made up? Is it a term for something specific? What does it mean, and what is it intended to encompass?

    • @GamesWithGabe
      @GamesWithGabe  2 місяці тому +1

      Thanks for the comment! It’s just a name I made up for the engine :)

    • @calvinwithun6512
      @calvinwithun6512 2 місяці тому

      @GamesWithGabe thanks for the reaponse!
      I'm taking a stab at making a D&D-like game, using a Pokémon-like aesthetic. I already wrote a library for the D&D mechanics, and I'm trying to make a graphical client for that code now. I am excited to see how much I'll be able to achieve, and your tutorial feels like it's going to provide a great launching-off point for my purposes :)

  • @DaniilBubnov
    @DaniilBubnov 3 роки тому +10

    Also (sorry for being picky) this is not a canonical ECS approach. It should be: components - data structured with no behavior, systems - functions with no state

    • @sorensaket5979
      @sorensaket5979 Рік тому +2

      The naming here is weird. The thing he is making is an Entity Component system. Not an ECS system or Entity Component System system. There are huge differences between the two and should not be confused with eachother. They are fundamentally different and the naming is unfortunate.

    • @User-oh8vi
      @User-oh8vi 7 місяців тому

      Do you have a source that explains what the canonical approach is? I'm not sure if the resources i've found are correct

  • @lengors7327
    @lengors7327 8 місяців тому

    Heyo, late to the party Gabe, but a few notes/opinions of mine for this topic:
    - First, I still think there are advantages in using a purely data-driven ECS even in Java, despite not being able to control the memory layout of the data. The first is that you have good separation of concerns (aka Entity will be a reference/id, Components will be associated with the Entity and contain all the relevant data but won't have any responsibility of performing some computation and Systems will have that responsibility instead)
    The second advantage is that it's much simpler to write multithreaded code with an actual ECS implementation rather than GameObject-Component one (Ill call it GOC from now on). On the GOC one your functions (for example the update) will run from every component. This means if you wanna start a thread pool and execute the same computation (lets say perform the euler method on a physics engine) for each component you will either have to make the first component start the pool and communicate between each component instance so the others don't start the pool and on top of that you will have to make it fetch all the other components of the same type to submit them and finally wait on all of them to finish or, alternatively, you could add a way to annotate component types and functions to tell your scene whether to perform the update on a thread pool or sequential (or some other form of parallelization). On the other hand, if you go with a ECS approach the system (in the example, physics system) can just query for all rigidbody components, and perform the Euler method using for instance a parallel stream map function which simplifies immensily the process of parallelizing the computation. On top of that, the system would be responsible for starting any threads it needs (if it needs something different from a simple stream map) rather than having to pass flags around or worst, make the code extremely complex if you go with the first approach.
    - Second, and this is just a personal belief, but I don't think Entities/GameObjects should ever have to have components added/removed after they are initialized. Rather the components themselves should be design in such way to allow for whatever dynamic data is necessary. But, I can see how having it can be useful at times

  • @cradledani
    @cradledani 4 роки тому +1

    This looks very interesting. Sub'd so i can follow your progress on this series.

    • @GamesWithGabe
      @GamesWithGabe  4 роки тому

      Thanks Atomizer! Every sub helps a bunch :D

  • @sconosciutosconosciuto2196
    @sconosciutosconosciuto2196 4 роки тому +3

    New sub :D

  • @elessarIT
    @elessarIT 2 роки тому +3

    Nice work! Can u please explain why inside the Font renderer you search if the game object has a sprite renderer and if so you print out "Font renderer found"? It is a typo?

    • @Clarsachh
      @Clarsachh 8 місяців тому

      I was wondering about the same.

  • @slavsquatsuperstar
    @slavsquatsuperstar 3 роки тому +1

    Do you ever just watch too many videos on ECS and go, "Isn't 'component' such a weird word?" xP
    Thanks for the great video, by the way. I was really hoping to find a Java implementation.

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому

      Haha thanks for the comment Eric! And I've thought about trying to code a Java ECS, I just haven't found the time yet :)

  • @DaniilBubnov
    @DaniilBubnov 3 роки тому +1

    Hi, thanks for the informative video, I have a question. I was watching ECS realated video and there ppl were also talking about cache misses and performance issues. Is it a real thing? Asking because I haven't found or seen any comparison to understand how important it is to keep the relative data closely to each other instead of just having them all over the heap

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому +3

      Hey Daniil! I'll try and respond to both your comments here briefly. I'd like to mention first that you are completely correct when you say this isn't an ECS approach (it's more of a "C"omponent only approach haha). This video was just to show what ECS is, and how to implement a component pattern that is useful for decoupling behavior from state. I didn't attempt to build true ECS in java, because if you are trying to build ECS, its better to do it in a low level language like C++, C, or Rust so you have direct control over memory layouts. In regards to whether ECS does help performance, and can reduce cache misses, I think that's debatable because modern hardware has so many different factors it's hard to say whether one change like this can reduce a cache miss or not. There is a very good video on this that Mike Acton does, and he gives a sample C++ program to demonstrate the potential performance increase in using ECS. However he reduces it to a trivial case, and the performance difference only becomes critical only when you have a very large amount of active entities (like 10s of thousands) which may not be present in an indie game. I'll reply to this comment once I find the video if you want to check it out (my ISP is down right now so I have limited internet access) 🙂

    • @DaniilBubnov
      @DaniilBubnov 3 роки тому +2

      @@GamesWithGabe wow, thanks for the detailed answer. I have watched some of the Mike's videos on ECS and now see what scale of performance is considered in data oriented way of ECS

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому +2

      @@DaniilBubnov great I'm glad you were able to watch some of them! And no problem man, I hope you're able to find a solution that works for you :)

  • @frankpoth154
    @frankpoth154 2 роки тому

    There are articles out there that emphasize adding/removing components on the fly, but I agree that a lot of games I enjoy would never need to do this and I have a hard time thinking of a need for it. Adding/removing buff components would be a good case for this, however. I'm sure it's very useful, but it's difficult to implement - at least for me.

    • @GamesWithGabe
      @GamesWithGabe  2 роки тому

      Hey Frank! I'm pretty sure I end up adding this later on in the series. If I don't add this in this series though, the way I would do it is by making a queue of components that are marked for removal. Then at the end of the frame you could destroy all the components that are queued for removal. That way you don't have any concurrent modification issues :)

  • @GarrethandPipa
    @GarrethandPipa 2 роки тому

    I am not a big java guy but... arraylists are not contiguous but arrays typically are because you allocate there size on the stack thusly int[] enityIds = int[200]; It works because they are immutable. arraylists are just fancy linked lists with decorators but their undepinning are still an array of pointers to memory that is not contiguous.
    Additionally referencing your components to entities the components store the index to the entity and the entity stores the indexes to its components called double indexing.
    When you remove an item form one of the arrays you pull the last item of that array and push it to the now vacated spot updating the new index. This in my opinion is the hardest part to wrap your mind around and implement.

    • @GamesWithGabe
      @GamesWithGabe  2 роки тому

      Hey Jeff, as far as I'm aware I believe even regular java arrays are just arrays of pointers (unless it's a primitive type). So it's not really possible to get objects in contiguous memory unless you do some hacky code like using a wrapper around some native C code that gives you some raw memory (I think lwjgl does stuff like this). This SO answer seems to give a pretty good overview stackoverflow.com/a/51603427 .
      And this indirect indexing method that you're talking about is the traditional way of implementing most ECS :). The guy who wrote the entt library has some great articles called, ecs back and forth, or something like that where he talks about some of the fundamental data structures that you can use for this, like the sparse set. It's definitely worth a read :)

  • @mwbgeometrydashpcaccount6372
    @mwbgeometrydashpcaccount6372 2 роки тому +1

    18:43 my spine shivered because it made a weird sound just like in one of the geometry dash videos

  • @lucd9642
    @lucd9642 3 роки тому

    Great episode, as always! But I'm wondering why don't you make deltaTime a variable in Window? Then instead of passing deltaTime to all update functions you can just get it by something like Window.get().deltaTime()

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому +4

      Hey Luc! You could definitely do it that. I like passing it in because I don't like calling Window.get() and using it as a singleton. I've actually moved completely away from this style of programming in my personal engine (and away from OOP in general), but there's nothing wrong with getting the value that way as well

  • @Ilumar589
    @Ilumar589 3 роки тому +3

    Great video. My advise to you if you plan to use the framework and it's not just educational is to write it directly as an ecs and not just ec. Yes, you don't have control over memory layout in java but that's not what you need, you just need control over continuous memory, that can be done via primitive arrays, byte buffers(on and off heap) of using unsafe directly. That being said it won't be idiomatic java so just write arrays of classes and use them as you would primitive arrays because when project Valhalla is finally done you can just add the inline keyword to the classes that act only as data and you will get the desired memory layout. Anyway, you got a new subscriber, keep up the good work!

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому

      Thanks Eduard! I do agree with you that using ECS is better than just EC (and it's actually what I'm doing in my engine that I'm working on off-video), but I think if you're gonna do the ECS you may as well do it in C++. I think that because if you want that much control over memory layouts and stuff, you may as well do it in a closer-to-the-metal language, but I definitely see your point too and it might be interesting to see the effects it would have on performance in Java. Perhaps I'll try modifying the Java engine one day to see :D

    • @Ilumar589
      @Ilumar589 3 роки тому +2

      @@GamesWithGabe There is nothing inherently faster in modern C++ compared to Java except for value types, if you want performance/lack of fragmentation you still need to do C style custom memory allocators. Honestly for indie games it's not worth the hassle. Between project Valhalla, Panama and the new low latency GC's you can get all the memory layout options and performance you need. Of course if you plan to release on consoles then you have no choice but to go the C++ route. Btw, you can try Rust instead of C++, much more coherent language. All the best on your journey!

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому +1

      @@Ilumar589 Thanks again! I definitely agree with you on the performance aspect, I differ on a couple points, but that's just my opinion haha. I have heard a lot about rust and I need to give it a try at some point, I'm actually starting to like C++ (which kind of scares me lol), but I do like learning about new languages and approaches :)

  • @aaronshed
    @aaronshed 2 роки тому +1

    You can control specifically how things are placed in memory, if you use an unmanaged language. You also didn't make an ECS system, you made a traditional OOP system

    • @monkey5266
      @monkey5266 2 роки тому

      So really ESC isn't really possible in java because of the garbage collector.

    • @aaronshed
      @aaronshed 2 роки тому

      @@monkey5266 You actually can, Java allows the use of unsafe code. I personally wouldn't recommend it though, you might as well use c or c++.

  • @thesituation5315
    @thesituation5315 11 місяців тому

    Hi, I'm not sure if you'll respond but I have a question that I'm very confused about. I've been following this and the physics series. I see that your Rigidbody extends Component, but I'm wondering what the Rigidbody's parent gameObject should be?

    • @jonispatented
      @jonispatented 10 місяців тому

      The rigidbody's parent GameObject should, of course, be whichever GameObject has the rigidbody. For instance, if you have a boulder that should have a rigidbody, then that boulder GameObject should be the parent of that rigidbody.

  • @andraantariksa4027
    @andraantariksa4027 3 роки тому +1

    Can you elaborate on what you have said in 8:15 , you said it's stupid if we do ECS pattern because arrays layout are not guaranteed, isn't Java have the same feature as C/C++ for this case?

    • @andraantariksa4027
      @andraantariksa4027 3 роки тому

      I mean you can use stack allocated array for that

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому +2

      Hey @Andra Antariksa , so I got asked a similar question awhile ago and found this Stack Overflow thread which references the JVM documentation stackoverflow.com/questions/10224888/java-are-1-d-arrays-always-contiguous-in-memory (the first two answers are the most helpful). They both basically say that since Arrays are implemented as objects, and the JVM places objects on the heap, and any data on the heap may not necessarily be contiguous, then arrays are not guaranteed to be laid out in contiguous memory. The main point I was trying to make though is that if you want low-level control over your data, you should probably be coding it in C++ where you have complete control over the data. Whereas trying to implement it in a language like Java involves a lot of guess work because it's very difficult to know exactly how and where your data will be laid out in memory, and exactly when the memory will be cleaned up etc.
      In terms of a stack allocated array, I'm not sure if you're referencing a special class that I haven't used, but in terms of regular arrays in Java, there is no way to allocate the memory on the stack, since once again they are implemented as Objects. I hope that helps a bit, if I misinterpreted any part of your question, or I raised more questions feel free to let me know :)

    • @andraantariksa4027
      @andraantariksa4027 3 роки тому +1

      @@GamesWithGabe thank you for your quick response! I actually want to implement ECS in Crystal language, not in Java. I watch your videos to get an insight to implement ECS architecture in garbage collected language.
      In Crystal they had stack allocated array, will it solve the problem?

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому

      @@andraantariksa4027 no problem! As for the Crystal Programming language, I have not used it, but from my brief look into it, it looks like it is also a garbage collected language. (Correct me if I'm wrong) If it is, then you can certainly try an ECS approach, but not having direct control over how the data is laid out in memory won't help very much when it comes to implementing it. For some good articles on how to write a good ECS, I highly recommend these: skypjack.github.io/2019-02-14-ecs-baf-part-1/ it's written by the guy who created entt (an entity component system that is very successful, it's even used in Minecraft :) )

  • @Speiger
    @Speiger 2 роки тому

    Dunno if you see this comment.
    But LWJGL3 has a class called StructBuffer which allows you to actually use ByteBuffers in a way where you can make ECS possible within Java.
    Since you can allocate memory like that quite easily.

    • @GamesWithGabe
      @GamesWithGabe  2 роки тому

      Hey Speiger, yep you can do ECS in Java if you want to, but I feel like ECS is a pretty low-level optimization where you're trying to get the best out of your memory layout. Java was purposely created to abstract memory away behind a garbage collector, so I feel like this is more a question of using the appropriate tool for the job. C, C++, and Rust are big languages that are very concerned with providing access to low-level memory management. So, if you want to implement something like ECS I feel like it would be better implemented in one of those languages :)

    • @Speiger
      @Speiger 2 роки тому

      @@GamesWithGabe "Better in other languages" true won't deny that. But LWJGL3 gives you access to native memory which technically is not controlled by the garbage collector (the ones that LWJGL3 provides) so technically with that you COULD work with that. And their memory allocator is insane fast...
      You forget that fact, and that would also allow you to align these values in a byte array which you get full control over.
      I mean memory alignment you have not much control over but BUT if you allocate 100MB of a byte[] you can be pretty sure its fully aligned. That means if you do wizzardry with byte[] to your data structures then you could achieve the same thing. LWJGL3 just gives you the tools to achieve the same thing easier.
      Point: Its not impossible, just annoying, other languages make it easier xD

  • @eskevv446
    @eskevv446 Рік тому

    So the ECS architecature if mostly for performance or convenience? Since you say it doesn't really suit Java as well as c++ for example, can we still justify it's use in garbage collected langauges? This confuses me because I thought even in Java elements in an array are all contiguous in memory, so why can't we also just pack the components together in arrays of arrays? Thanks for this awesome series Gabe, I'm really enjoying it :)

    • @GamesWithGabe
      @GamesWithGabe  Рік тому

      Going full ECS is typically done for performance reasons. Chunking up the data related to your game object into smaller pieces (components) is helpful for your CPU cache since it can fit more of them in L1, L2 or L3 cache without having to hit main memory. ECS does have a useful way of thinking about architecture though which is often parroted in the Java community as, prefer composition over inheritance. When people say this, they're basically saying to make something like an ECS because it makes code easier to reason about.
      In Java it's not really worth it to put all your objects in the same array, because it's not guaranteed to be contiguous in memory. It actually sounds like it probably won't be to reading through the spec here docs.oracle.com/javase/specs/jls/se19/html/jls-10.html . It talks about how cloning an array makes a shallow copy, and how an array of type T[] will store a reference of T. This implies that the arrays don't store the data itself continuously, but rather pointers to the objects (which is fine because the JVM is modelled to deal with this and has some performance tricks to help out). So I would say it's not worth it to store everything in arrays and try to micromanage your memory because it likely won't work out in Java.
      Hopefully that clears it up a bit, but it's a great question and I'm not completely sure how the JVM will handle all this. So, as always, you should profile your code to see where the true bottlenecks are if/when performance is a problem :)

    • @eskevv446
      @eskevv446 Рік тому

      @@GamesWithGabe I was reading about how Java stores references as well, and why objects still end up getting moved around in memory even inside of an array, which results in those cache misses we try to avoid. The gargbage collector basically wants to keep all heap memory compact to make allocation easier. But this is honestly the perfect answer in such a short amount of time. Thanks 😄

  • @ivansantiago3458
    @ivansantiago3458 2 роки тому

    In data-oriented programming, if some entity has more than one box collider wouldn't there be a problem? How could it be solved?

    • @GamesWithGabe
      @GamesWithGabe  2 роки тому

      Yea typically most entity component systems don't allow multiple components of the same type for one entity. You can usually get around this by just creating some sort of parent-child component for entities, and then adding a child with the extra component. You could probably even do this all behind the scenes in code so the user just feels like you can add multiple components of the same type per entity, but it's really adding new children with the component

  • @roamingcelt
    @roamingcelt 5 місяців тому

    In removeComponent you have a loop. That loop only runs to the first instance of that component before returning. Why? This doesn't make sense.

  • @asherhaun
    @asherhaun 3 роки тому

    how do I change gameObject values, I attempted to change the Transform property with a setter "setTransform(Transform t) {transform = t}" and although it does update the transform, I don't see the position change (fyi, I am a few videos ahead, so I just finished the batch renderer)

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому

      You may want to take a look at the dirty flags video, I think it's the next video or so. I would also recommend being wary of assigning objects like that. When you pass in the entire Transform object and say transform = t, you're not making a copy of that transform, but rather reassigning a reference. This article looks like it explains this concept pretty good javarevisited.blogspot.com/2015/09/difference-between-primitive-and-reference-variable-java.html . Whenever I want to copy a transform's values, I typically create a function that does something like Transform.copyValues(Transform from, Transform to) and then just copy all the floats, that way you retain the original transform and just copy the values.

    • @asherhaun
      @asherhaun 3 роки тому

      ok, that sounds reasonable, thanks. even still, it doesn't update the visuals

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому

      Yea, copying it may not update the visuals because you still need to upload the changes to the GPU by updating the VBO that contains the draw data. The dirty flags episode is about solving that, let me know if it still doesn't update after implementing that portion :)

    • @asherhaun
      @asherhaun 3 роки тому

      Alright, I will get back to you on that, thanks!

  • @denvercox7675
    @denvercox7675 3 роки тому

    So you cant do a true entity component system in java because the arrays are not guaranteed to be continuous? Recently I have heard of a class called "Unsafe" which as its name suggests is not safe, but it has a method that allows dynamic allocation of memory, similar to C's "malloc" method. do you think this would allow a true entity component system in java?

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому

      Hey @Denver you can definitely use something like this to create an entity component system in Java :). The only problem I have with doing something like this is that it feels like you're working against the language to get the job done. Whenever it starts feeling like I'm fighting the tools I'm using to do something, I ask myself if I'm using the right tool for the job. I think that was more of the reason I said I wouldn't consider making an ECS in Java

    • @denvercox7675
      @denvercox7675 3 роки тому

      @@GamesWithGabe yeah that makes sense, thank you for your reply!

    • @GamesWithGabe
      @GamesWithGabe  3 роки тому

      @@denvercox7675 No problem :)

  • @huangwilliam9880
    @huangwilliam9880 2 роки тому

    Do you think using a Set is better than a List for storing Components? I don't see how the order of Components matters for a game object.

    • @TheBEstAltair
      @TheBEstAltair 2 роки тому +1

      Sets can't contain duplicate elements though. Wouldn't that be then up to the Equals methods of Components on whether 2 very similar Components can be placed in the same set?
      With List you don't need to worry about it...

    • @huangwilliam9880
      @huangwilliam9880 Рік тому

      @@TheBEstAltair alright, thanks for telling me.

  • @hrithikverma2761
    @hrithikverma2761 4 роки тому +1

    Dear can you help me I wanna develop games how do I get started. I am completely a beginnet

    • @hrithikverma2761
      @hrithikverma2761 4 роки тому

      Please help sir. 😊😊😊😊

    • @GamesWithGabe
      @GamesWithGabe  4 роки тому

      Hey hrithik, if you have no experience programming, I have a beginner programming course playlist that you can follow. If you already know how to program in Java, I would suggest starting out with my Pong or Snake series, they start out by building games and not worrying about game engines.
      Some good resources that I used when I was first learning to program games are these:
      * www.amazon.com/Foundation-Game-Design-HTML5-JavaScript-ebook/dp/B00ACC6AU0/ref=sr_1_fkmr0_1?dchild=1&keywords=game+design+rex+van+der+spy&qid=1588352785&s=digital-text&sr=1-1-fkmr0
      * www.amazon.com/Advanced-Game-Design-HTML5-JavaScript-ebook/dp/B01JCM6SXY/ref=sr_1_fkmr1_1?dchild=1&keywords=game+design+rex+van+der+spy&qid=1588352844&s=digital-text&sr=1-1-fkmr1
      * gameprogrammingpatterns.com/
      And another great UA-cam channel that helped me:
      * ua-cam.com/play/PLRIWtICgwaX0u7Rf9zkZhLoLuZVfUksDP.html
      After you have a basic knowledge, I would suggest just trying to make a game, and then you'll start to see where you will need more help. Let me know if I can help you out in any other way! :D

  • @Bandit-is8zi
    @Bandit-is8zi 4 місяці тому

    8:03 We can block the road so the garbage truck cant come to pickup garbage :)

  • @syntaxed2
    @syntaxed2 2 роки тому

    When referring to JAVA as a "garbage collected language" I sometimes like to omiss the middle word :D

    • @GamesWithGabe
      @GamesWithGabe  2 роки тому +1

      Lol, I would tend to agree, but unfortunately the more I work with other languages I feel like that could be said about all of them :)

    • @syntaxed2
      @syntaxed2 2 роки тому

      @@GamesWithGabe So true :D anyways, good contents on this channel!

  • @therunnerproject
    @therunnerproject 2 роки тому

    Nice explanation for ECS, it's just a shame that you only implement the component pattern in the end, due to the limitations of Java.

    • @GamesWithGabe
      @GamesWithGabe  2 роки тому

      Thanks! And yea you can still make one in Java if you would like, but it's a bit easier to work with memory in a lower-level language like C++. I found a great tutorial for C++ ECS though if you're interested www.david-colson.com/2020/02/09/making-a-simple-ecs.html :)

    • @therunnerproject
      @therunnerproject 2 роки тому

      @@GamesWithGabe Thanks. I am currently working on an ECS with C#, there you also have the opportunity to work with pointers and unmanged memory. Unity also created their ECS entirely in C#.

    • @GamesWithGabe
      @GamesWithGabe  2 роки тому

      @@therunnerproject Yep C# is a much better language to use when you want to deal with lower-level memory stuff. Good luck with your project though :)

  • @leke13_beats
    @leke13_beats Рік тому

    This video doesn't support subtitle translation. 😔

  • @oftenyoutuber4348
    @oftenyoutuber4348 Рік тому

    18:43 there's a weird sound

  • @sconosciutosconosciuto2196
    @sconosciutosconosciuto2196 4 роки тому

    How can you destroy a Gameobject?

    • @sconosciutosconosciuto2196
      @sconosciutosconosciuto2196 4 роки тому

      With a function like destroy()

    • @GamesWithGabe
      @GamesWithGabe  4 роки тому

      Hey sconosciuto, I found that the best way to destroy game objects is by having a list called objectsToDelete, then you can call Scene.destroyGameObject() and add the game object to the list. Then at the end of the frame, you remove all the game objects that are pending to be deleted. If you just wanted to call gameObject.destroy(), you could do something similar where you set a flag on the game object that says shouldDestroy = true, then at the end of the frame remove it from the game objects list. The reason I suggest waiting til the end of the frame is because you could have issues with concurrent modification. I have an example that you can look at here: github.com/codingminecraft/Mario/blob/master/src/main/java/com/jade/Scene.java in the function deleteGameObject :)

    • @sconosciutosconosciuto2196
      @sconosciutosconosciuto2196 4 роки тому

      @@GamesWithGabe ok thanks, but there is a problem. I can't store the reference to a gameObject anywhere else.
      For example in another component I can't store a GameObject reference to another gameobject (a component that uses a pathfinding algorithm to search the path to another GameObject for example).
      Because otherwise it wouldn't be destroyed by the GC and the component would search a path to a Gameobject that should be destroyed..
      The same problem exists with components (I can't store a component reference inside another component)
      Probably I'll switch to C++

    • @GamesWithGabe
      @GamesWithGabe  4 роки тому

      Hey Sconosciuto, this problem will persist in C++. There are different design decisions that you could make to try to alleviate this problem, but you will always have to check if the gameObject/component still exists if you are trying to store references to it. Check out these stack overflow questions:
      gamedev.stackexchange.com/questions/148833/how-to-handle-entity-initialisation-and-destruction
      gamedev.stackexchange.com/questions/115580/how-to-handle-gameobjects-that-have-been-destroyed-but-are-still-held-by-others
      You'll notice that one of the answers in the second question says that you can do a system like the one I suggested, where the entity is removed at the end of the frame in a clean-up step if it gets destroyed, to prevent errors within the frame. But, you will still need to check for null objects. This problem even persists in professional game engines, take a look at these questions about Unity and Unreal:
      answers.unity.com/questions/1688939/code-still-trying-to-access-object-that-has-been-d.html
      stackoverflow.com/questions/58997811/ue4-how-can-i-detect-if-an-actor-refrence-has-been-destroyed-in-blueprints
      So, I would advise in trying to find a different solution for the specific problems your suggesting. Perhaps make a copy of the position of the entity you are trying to pathfind to, and if that entity is destroyed I think that it would be an error anyways if your AI tried to continue to pathfind towards it. I'm planning on switching to C++ myself pretty soon, but it's because I want to learn more about low-level memory management and see if I can improve performance. Problems like this will still exist in C++, they will just take on different forms :)

    • @sconosciutosconosciuto2196
      @sconosciutosconosciuto2196 4 роки тому

      @@GamesWithGabe ok :D

  • @oftenyoutuber4348
    @oftenyoutuber4348 Рік тому

    FUN FACT: This video was published on my 11th birthday! But now I'm 13

  • @BrandonLamb1
    @BrandonLamb1 4 роки тому +3

    Trying to understand if ECS is understood here. The java code doesn’t seem to be an implementation of ECS. Components should not have functions/behavior, basically just a struct. This felt like copying unity gameobject style. I guess the title of this video may mislead someone into thinking this is an example of a proper ECS implementation, which is where I was left scratching my head. Also curious on the accuracy of Java arrays not using contiguous memory, might be something to google next.
    Am I understanding this video is really not ECS but about implementing a component style architecture? Seems like a step up from OOP inheritance tree but on par with what unity is already working on replacing with proper ECS, which they claim big performance improvements which should also apply to JVM as both are GC managed languages?
    Interesting video still!

    • @GamesWithGabe
      @GamesWithGabe  4 роки тому

      Hey Brandon, thanks for the comment! This Java code that I write in this video is definitely not ECS, but rather the Component Pattern as outlined in the gameprogramming article in the description. I also mention that I won't be employing ECS in the code because Java is garbage collected, and we have no control over memory space.
      On my comment about the Java arrays not using contiguous memory, I didn't mean a single array would not be contiguous in memory, but that two arrays declared next to each other may not be contiguous. However, I came across this link which suggests that even arrays may not be contiguous: stackoverflow.com/questions/10224888/java-are-1-d-arrays-always-contiguous-in-memory
      Also, Unity is working on ECS, but the reason that they can implement it in C# is because they have written their own compiler, the Burst Compiler. This means that they are directly controlling how the C# gets compiled down to machine code, which also means that they still have control over how the memory is being laid out. You can read up a bit more about that here: blogs.unity3d.com/2019/02/26/on-dots-c-c/
      Once again thanks for the comment, and for thinking critically about what I propose in the video! The last reason that I have not tried to improve the pattern that I use in the video is because it's simple conceptually, fast enough, and it works. If the game you're writing suddenly starts losing frames, I think profiling is the way to go to see what the performance critical part of your code is :)

    • @BrandonLamb1
      @BrandonLamb1 4 роки тому

      GamesWithGabe hmm interesting, definitely something I’m interested to try to find out more on. I’ve been trying to soak up as many videos as I can on this stuff, it’s super fascinating. I’m using Godot but wanting to make a multiplayer server in java or rust and code organization is an important piece to get right. Thanks again for video, also recommend checking out kotlin, makes some of this code much easier/concise. Cheers!

    • @BrandonLamb1
      @BrandonLamb1 4 роки тому

      GamesWithGabe curious, even if not stored contiguous in heap wouldn’t you still gain performance by not pulling your entire player object as you would fill caches more likely as part of the benefit is only pulling the data needed.. if you request 100 monster objects that contain all components, jvm or cpu will pull the entire memory they use assuming you will use it when you only may be using transform? Seems like you may still gain benefit. Still reading that SO article, good stuff

    • @GamesWithGabe
      @GamesWithGabe  4 роки тому

      Hey Brandon, I would assume you would still get some performance gain, however I'm not sure how much haha. I did some tests with a fake "game" where I simulated a player playing for 30 minutes at 60FPS using ECS, and then the same code without ECS, and I was consistently seeing a performance improvement of about 300 microseconds (I wrote this test in C++, the repository is here if you wanna take a look github.com/ambrosiogabe/ECSExperiments). I'm not sure how accurate my test is, since it's not an actual game, (and I don't even know if I coded the ECS part right, I'm still learning too haha), but I definitely want to do a test in the future where I code the same game twice, once with ECS and once without it to see what kind of performance benefits there are because I haven't been able to find any good benchmarking suggesting that using ECS will give a huge performance gain.
      Also, I will definitely take a look at Kotlin, however I have been planning to switch to C++ pretty soon, so I may not end up using it haha. And, good luck with your project! It sounds super interesting and I've been wanting to dabble in multiplayer for awhile now, so let me know how it goes :)

  • @jimraynor3767
    @jimraynor3767 Рік тому

    This is very good, but I get monkeypox from that gay background music

  • @makispapa5867
    @makispapa5867 Рік тому

    Why not just use HashMap.newHashSet for your components and just iterate like for (Component c : components) instead of for (int i=0; i < components.size(); i++).
    Makes more sense to make components thread-safe in a game engine.

    • @GamesWithGabe
      @GamesWithGabe  Рік тому

      You can't have two components of the same type with a hash set which is why I used a regular list. Also, HashSet isn't thread safe on insert or removal. And if it was, you would have to do some heavy modification with some plans on how to support a multithreaded logic update loop for your game engine :). I think most modern game engines prefer to multithread large systems like physics, audio, rendering, input, ai, etc. Instead of multithreading at such a granular level to avoid synchronization costs as much as possible