In Unity ECS, a system is a class inheriting from component system, and we can override its event methods, which include onCreate, onDestroy, and onUpdate. The update method is called once per frame, and we can use attributes to specify when the updates are performed relative to updates of other systems. In this example of mySystem, the attribute says that it should update before other system, and otherSystem, meanwhile, says that it should update after mySystem. These attributes are, of course, logically redundant, so we only need one of them. If though we were to specify a logically impossible order, like both updating before the other, Unity will throw an exception upon the creation of these systems. In cases where we don't specify which of two systems should update before the other, Unity picks the order for us. In general, we should leave the update order unspecified, except where we really need this control. The systems of a world are placed into logical groups. When a group updates, all of its systems update. We can create whatever groups we like, and we can create subgroups within groups, but three groups are created by default, an initialization system group, a simulation system group, and a presentation system group, which are updated in that order. In this example, both systems are explicitly added into the simulation system group, which is actually the default. In the editor, looking at the entity debugger window, we can see a list of all the systems in their execution order. You can see here the my system and other system, along with other default systems, which we'll discuss later. If we look at the full player loop, you can see where the system group updates execute relative to the mono behavior events. As you can see, the initialization system group is updated just before early update, the simulation system group is updated just after the regular update, and the presentation system group is updated just before post late update. In a system, we can create and use entity queries, like we've already seen, but when we do so, we should create the queries using methods of system itself rather than the entity manager. This is not just more convenient, it allows the system to track which queries are used in the system. A system with no queries will update unconditionally, but as soon as we add at least one query to a system, the system will skip updating when no entities match its queries. Rather than wastefully create an entity query every update, we generally should just create it in the system's onCreate method and reuse it every frame. Be clear though that the chunk and component arrays we get from a query should not themselves live beyond the end of each update because the underlying data may change. An entity query builder provides a more convenient way to iterate over components of a matching archetype. Every system has an entity query builder field named entities, and when we call its forEach method, we pass in a lambda. Using introspection of the lambda parameters, forEach builds an entity query and calls the lambda function once for each entity of the matching chunks. In this example, the query matches chunks with component types compA and compB. The lambda function increments x of the compA value with x of the compB value, and then it removes the compB component from the entity. There's quite a bit of magic going on here, for one thing, creating a lambda every update would normally create wasteful garbage, but the Unity compiler especially avoids this. Second, the components are passed as refs so that mutations to the parameters aren't just local to the function. Third, when we mutate the component, we are actually mutating a copy, but when the lambda returns, forEach copies these values back to the actual components stored in the chunk. As you can imagine, this arrangement is less optimal than directly iterating over the components in the chunks. The reason forEach must make these copies is because creating entities, destroying entities, or adding or removing components are all structural changes. They require modifying the chunk structure or moving entities between chunks. Once we make a structural change, any arrays of chunks or components that we created before the change can no longer be used even if their data was unaffected. To work around this problem without using forEach, we can record the changes we want to make with an entity command buffer and then play back those changes later. These entity command buffers are created from special systems called entity command buffer systems. By default, the buffer created from one of these systems is played back when that system updates. Once played back, an entity command buffer cannot be used again, so we generally need to create new buffers every frame. In this example, we first get the end simulation entity command buffer system, which is created by default and is updated last in the simulation system group. From the system, we create an entity command buffer, which has most of the same methods as an entity manager. Here, we use the buffer to create an entity and add a component, but the changes are not enacted until we call playback passing in the entity manager. It's an error to call playback more than once on the same buffer, and so to prevent the end simulation entity command buffer system from calling playback like it normally would, we set should play back on the buffer to false. The iBufferElementData interface defines a component type that stores an array of values rather than a single struct. These arrays have a fixed number of slots that are stored directly in the chunk, but these arrays can grow by storing any number of additional slots outside the chunk, hence these are called dynamic buffer components. In this example, we define an iBufferElementData called myBufferElement with two int fields. The internal buffer capacity attribute specifies that dynamic buffer components of this type will store five of these elements directly in the chunk for each entity. Along with the five elements, the component stores a length and a pointer. When the component's capacity of five has exceeded, more memory is allocated outside the chunk and the pointer is set to point to this memory. So in code, we add a dynamic buffer component to an existing entity using the addBuffer method, or we include the component upon an entity's creation. We use getBuffer to retrieve a dynamic buffer from an entity, and we can add elements to the buffer with the add method. Note that after adding one element, the length is one because it started out at zero even though the internal capacity of the buffer is five. If we were to add more than five elements to the buffer, the extra elements would be stored outside the chunk. Also note that when we retrieve a value from the buffer, we are getting a copy of the struct, so here to actually mutate the buffer, the element must be assigned back to the same index. Finally, when we remove the element at a given index, all elements following it are shifted to fill in the gap. When working with chunks, we can access the dynamic buffer components, much like we do for regular components, except we call getBuffer accessor passing in an archetype chunk buffer type. To access entities in their components and jobs, we use special job types and we use job component systems to help us chain appropriate dependencies between our jobs. An ijobChunk iterates through chunks of a query, processing each chunk in its own subjob. An ijobForEach iterates through entities of a query, optionally processing the entities in multiple subjobs. The ijobForEachWithEntity does the same, but accesses the entity IDs as well as the components. In this example, we define an ijobChunk which accesses the compA and compB components of the chunk. The execute method receives three parameters. The first parameter receives the chunk, the second parameter, chunkIndex, receives a value that should be using conjunction with concurrent entity command buffers, as we'll explain later, and the third parameter receives a cumulative count of entities in all chunks with smaller indexes. For example, if the chunk at index 0 has 20 entities and the chunk at index 1 has 30 entities, then the first entity index value for the first three chunks will be 0, 20, and 50, respectively. Anyway, this parameter is not really useful in most cases, but I mention it for completeness. To use this job, we assign an archetypeChunk component types to its fields and we call schedule passing in a query which determines which chunks the job will process. When the job runs, execute is called once per chunk and each execute call runs as its own subjob, only once all the chunks have been processed is the job finished. Much like how the job system safety checks ensure that no two concurrently scheduled jobs access the same native container unless the access of both is read only, the job system safety checks also ensure that no two concurrently scheduled jobs access the same entity components unless the access of both is read only. So here, if we schedule another instance of my job while the first is still scheduled, the safety checks will throw an exception because both jobs access the compA component in the same chunks. The two jobs conflict and so we must either complete one job before scheduling the other or schedule one job as a dependency of the other. Either way, it should be determinant which job always finishes before the other starts. Note that the compB component is marked read only in the job and this is what tells the job system that it's okay to concurrently schedule a job with other jobs that also access compB as read only. When we define the archetype chunk component type for compB, we pass Boolean true as the argument and this makes the component array that getNativeArray returns read only such that attempting to mutate that array will trigger an exception. So when we want to access a component read only in a job, we effectively should specify that the access is read only in two places, not just one. Job component system is a variant of component system that helps us configure job dependencies across systems. When we use a job component system, we should create queries and archetype chunk component types for our jobs using methods of the job component system rather than the entity manager as we have done so far. Here for example, we're calling the get entity query and get archetype chunk component type methods of the system not the entity manager. Creating the query this way registers it with a system and it is assumed that jobs created in the system will use the queries registered with the system. On updates of job component system expects us to return a single job handle representing all jobs created in the update. So if we create multiple jobs, we should make the jobs dependencies of each other or use the combined dependencies method to combine them into one job handle. The returned handle will be completed for us at some point later at the very latest before the next update of the same system usually though completion happens upon the next structural change because to avoid conflicts structural changes trigger a hard sink point. These sink points complete all outstanding jobs that touch entities and components of the same world. The job handle parameter of an update is passed a job handle representing all jobs returned by other job component systems which may conflict with the queries of this system and so to avoid conflicts all the jobs we create in the update should depend upon the input job handle either directly or indirectly. In some scenarios this does create dependencies that aren't really necessary and thus may create inefficiencies but we can always work around these problems by splitting the jobs created in one system across multiple separate systems. I job for each is an alternative to I job chunk that is sometimes more convenient and despite the name it doesn't share the performance drawbacks of the entity query builder for each method that we saw earlier. This example implicitly creates a query that matches chunks with both comp a and comp b. The first attribute excludes chunks that have comp x and the second attribute requires the chunks to also have comp y even though we do not access the comp y components in this job. For each entity the components we actually access are passed by rough to the execute method such that mutations to the component parameter directly mutate the component in the chunk. Note here that the comp b parameters marked read only so we cannot mutate it. The I job for each with entity variant passes the entity id to the first parameter of the execute method. If though we want to make structural changes as we iterate through the entities we must use an entity command buffer like we've seen before but because the buffer in this job may be used concurrently in separate subjobs we must use the concurrent form of entity command buffer. Here we see how this job can be created and scheduled. We create an entity command buffer from the end simulation entity command buffer system but we make it concurrent by calling the to concurrent method. When we schedule the job we give it the input dependencies of the job component system like we always should but notice we pass the system itself as the first argument rather than a query. The schedule method itself uses a system to create the query using introspection information from the job. If instead of the regular schedule we call schedule single then the job would be processed in one logical subjob rather than split across many in which case we wouldn't need a concurrent entity command buffer because then the buffer would only be used from just one thread. When an entity command buffer is played back it may make structural changes but rather than trigger a hard sync that unnecessarily completes jobs unrelated to the changes entity command buffers only complete jobs that are explicitly registered to require completion before playback. By calling add job handle for producer here we're telling the entity command buffer that this job must be completed before the buffer playback. Finally there are a good number of odds and ends I haven't covered here most of which I may not cover anytime soon because they are still under documented and highly subject to change. In some follow-up videos though I'll walk through some more practical examples and we'll look at some of the packages Unity currently has in development that are related to ECS including hybrid dot rendering unity.transforms and unity.physics


Hello. Oh, welcome. Oh, wow, even more people. Wow, I'm not used to so many people. Usually, I just talk about Haiku and there's like 20 folks. So yes, you can actually script the web with Reboob. So just a quote I found from Tim Berners-Lee, who said the web is about transmitting information to everyone regardless the platform. When he says information, it doesn't really mean the look or how many pixels to the left or the right. It's just information. Except CEOs just want their website to look everywhere the same at the pixel. So basically, there won't flash, not the web. Wonky. So when you want to find data on the web, you need to open your browser, go to the URL, wait for megabytes of HTML, GS, CSS, sometimes flash. Well, that's not really part of the web, but anyway, to load. And then maybe when you scroll down the page, you can find something interesting. Some people know about control F, but you need to know what you are searching for. So basically, you iterate until you find. You could be paced. You strip the spaces and whatever. But then it's a bit late, so you go to sleep and you don't profit from it. So what if we could just do something? URL, or ID, or pattern, or whatever. Pipe, grab, pipe, cut, pipe, something. And just profit from it. Of course, there's curl, wget, but you just get the HTML without the CSS, the JSON. So it's just not the data. Sometimes the data is not even on the HTML code itself. It's sometimes inside a JSON file taken from an adjax call or whatever. So here comes Reboob. In its web outside of browser, no ID don't come out with the name. So if you have complaints, make the others. There's usually, every time we try to get a release in Debian, there's a lot of trolls about it, but I'm not responsible for this. And basically, you have many modules that can be instantiated as backend, so you can have the same module for two or three websites. And they implement capabilities, like bank, video, and whatnot. It's written in Python, and there is a Python framework for it. There are command line tools. There are also GUI tools with QT. So the framework, as I said, separates information into different capabilities, video banking, messaging. Messaging can be mails, but also tickets on a bugzilla or whatever. And you can either pass it a URL, or an ID, a unique ID at the backend. And of course, you can search for things. And it also emulates a web browser for the module to get the data. So both HTTP calls using your different, the existing Python frameworks, and also passwords for HTML, XML, JSON, and even PDF, because sometimes you want to extract information from bills, and the bills you get are PDF files. And the web browser engine has been rewritten, so it's even now even easier to use. Here you've got some of the modules. There's a whole list on the website. So as I said, tickets are basically messages. They are handled like emails, so you can actually write a gateway to email something. It ends up in the backtracker of your choice. And also, French banks, maybe some others, I'm not sure. I don't really check. They are used by real companies to do real stuff, like Bujair and Cosy Cloud has a module that uses Reboop to get banking information. That's something Cosy can do, because they are very small, that Google really wouldn't even want, or even dream about doing, because everyone would go at them and say, oh no, you won't get my bank account info, as well as my mail and everything else. They're also shipping providers, so you can actually use Reboop to track your shipping. And video, of course, even with the Libre software meeting videos. I looked at the first-time site, but it didn't really have a search field, so it won't really be very useful. And then you can even search for jobs. So writing a module in Reboop, you just need to provide a few files. Well, you need to just list the base module class. And then module, browser, and pages. And you, of course, need to write a test, because websites break. Most of the icons in Reboop are really crappy on purpose, because we didn't want to infringe trademark or whatever. So yeah, let's try to make a module in Reboop. There's a tool called boilerplate, which actually writes the skeleton for you.  Then you update the module database, and you can check the info of your already created module. And by the way, if you don't want to install Reboop, just to try it, you can actually use localrun.sh and pass it the Reboop commands, it will just work. After a git checkout or whatever. So let's just have a look at it and fill the blanks. And you can also, of course, look at all the modules to see how they do things. But first, as I said, sometimes the data is not in the HTML code, and the HTML code used to change a lot, because, well, people don't like stable things. And it just really needs a lot of escaping, and persons, and whatever. And sometimes the declared encoding is wrong and whatever. So before you try to pass the HTML, just make sure you don't have the nicely formatted gson data or XML or whatever. And make sure you locate only the data you want and not some other junk. So the module we just got, it just exports the module class itself. So we just subclass the base module. And for a job module, we have three functions, three methods to provide. The advanced search with separate fields is optional. On the website, I targeted there's not really any advanced search, so just empty, just not provided. And basically just passes the code to the browser class. The browser module class, sorry. So it maps the different URLs you can have on the website to pages to parse. So you can have a search page, a job page, whatever. So you can provide it with regx to filter the different URLs. And that's the code. So it just also forwards the request to the correct page class. And there we go. So that's where the real work is. So I'm not really entirely familiar with the some of the Python syntax, so the ads method and whatever. So I dug it a bit, but I will not really be able to explain you exactly how it works. But basically the interesting part is below. So you can use filters to say I want the clean text of the title, tag for this field and whatever, and we'll just iterate over the page. So that's just to get the job adverts. And for the search page, you also just iterate over the results and just say take the anchor tag which have this class. And then for each item, you just want to take the link item that we are and use a reg exponent and then take the results. So it's really a few lines and you've got the data you need. That's not really the full text because there are some more fields, but at least you get a title, the description and the idea. So now we can actually test it. So we should be able to find at least one Linux related jobs on a site called Linux jobs. So we just ask the backend search job Linux and we just make sure that's at least one. So let's do it. So we update the module database and we can query for a job by specifying this backend only or else it would just go to every configured backend. Since it hasn't been configured yet, it would ask you if you want to do it. You can enter some fields and just run the search with some more options to debug and whatever. Then you can query the info for this ID at Linux jobs and then run the tests. And before you upstream your patches, please make sure you have actually running tests and the other Python syntax tests are okay. Now we have command line tools. So command lines is nice. It has an interactive interface, but sometimes you want just the data and you don't want to fill out with the formatting. So we provide a large list of formats for you, CSV, JSON, whatever. So we can do for example, hey, let's search for Python jobs on this website. Put this in a CSV file and because LibroFist doesn't really like SED in, so we just make a temporary file and then launch LibroFist calc with the proper CSV filter parameters to make sure it will read the CSV file correctly because there are many different flavors. And then you will just get a spreadsheet of all the Python jobs. But you might also want to use the framework. So for example, here's what you would do to see what's in your bank account. If you just import Reboob, you import the capability from the bank type. You just get an instance of Reboob, you load the backend for this capability and you can iterate the accounts and see what's in the balance. So hopefully you've got some profit. We can also do some other stuff. Like I showed you a job module. Well, you can actually say things like, well, let's load the backends for the job modules and for each of those words, we will use this tag cloud library that I found. There are some others as well. And we'll just make a tag cloud of all these words with a size depending on how many jobs we found. So we just count how many items are in the list when we iterate over the result of the job search for each of these words. Or one. The actual code has some more checks because, yeah, that's way enough. Because well, the code was crashing inside SDL so you have to have at least 10 as a size, but well. And then you create the tag and it looks like this. So it's an interesting way to show what's inside the website. We also now have a continuous integration system because well, people love breaking their own websites. Who knows why? But because we rely on them for important data like bank account info, especially for real companies, we actually have to fix it real soon. So now we know this module broke this test and we can fix it. So if you want to contribute like, so you have a website that's providing job offers and you want people to be able to use Reboop to search your website, you can now send us pull requests on our own GitLab server. If you are publishing a website, please, please, please stop breaking them every time. We also welcome donations to the French nonprofit that supports the project. So you can become a member of the association. And there's also professional support available. So if you want to use Reboop for a professional system, you can have real assistance without having to dig yourself. And whoa, I was quite fast. So thank you. I hope you understood everything. And well, I welcome both your questions and your patches. Questions? Yeah. They do. I'm curious how you use the hang of updating, downloading a packet with your distro and updates every six months is a bit more. Yeah, so question was, you are quite optimistic about websites not breaking every two weeks and how do you handle module updates with regard to distro packaging, which tends to actually, yeah, been sometimes several years behind. You've seen the Reboop update command. Now you can actually use Reboop with the updates that come in. It actually fetches directly from Git. If possible, so you can actually install Reboop yourself and you get the modules updated regularly without relying on the package management system, which is a bit sad because I either don't really like having to go around the proper package management system, but for this kind of things, you don't really have the choice. So there's another Git repository with only the official modules that are maintained there. Well, so what are the advantages of Reboop against like Scrappy? I don't really know Scrappy much. I've used things like YouTube, DL, or whatever for videos, but not really anything else. So I can't really say, sorry. A bit louder, please. So are you able to handle content generated by JavaScript, like ad-ex requests? I don't know if we already have a module that does it. I think sometimes websites want to generate hashes and stuff like that on the client side to validate the input of the ad-ex requests or something like that. I'm not really sure I would have to check the modules, but I know some modules actually emulate ad-ex requests to actually get JSON data instead of passing ugly HTML code, sorry. So stack over flow, can you search stack over flow? Oh, so can you search stack over flow? I can tell you. Dev Reboop, STA, I don't have any module that starts with STA, so you can send a patch, please. So is there a reference implementation for banking modules outside of French banks? I'm not actually sure that there are only French banks, but I only know about them. I didn't really check all the modules because they are quite a large list. But there are so many, I think some banks like AXA Bank, Bank, maybe International enough that they also handle the non-French versions, I'm not sure. So you'd probably just want to ask an IRC maybe. By the way, yes, we do have a Reboop channel on FreeNode if you want to join and ask questions, I don't have the answer for yet. More questions or? Okay, well, thank you very much. Thank you a lot. And you will have as those speakers Belgian chocolates.


But we cannot control those outcomes with this sort of debate. So let me read you the very first thing I wrote down in prep. I can finally answer the question we get. The ladies' jail of death destroys individual autonomy forever. My name is Ryan Guy, and I am the instructor of Modesto Junior College's fully online Introduction to Debate course. Historically, this has always been a class that was offered with a face-to-face component. Advances in video conferencing technology have made it possible for ours to offer this class in a fully online modality. This is an exciting development as it allows anyone with fast internet to take the course, meaning that your classmates might just be down the street or could be on the other side of the globe. As you consider taking this class, there are a couple things you should keep in mind. First, as you may have noticed on Pirates Net, there is still a listed class meet time for this course. These live class meetings will take place each week via a video conferencing system. The specific time for your class section can be found on the course description on Pirates Net. In order to participate in these sessions, you will need access to a computer, a webcam, and a fast enough internet connection to be able to join the video conferencing. I find if you can stream HD videos on YouTube or Netflix, your connection is fast enough. To take advantage of the full functionality of our campus video conferencing software, you will also need to use an actual computer. Any modern desktop or laptop will work great. Unfortunately, smartphones don't quite have the processing power needed to use some of the advanced tools that are necessary for this course. It's important to understand the outset that these live class sections are required part of the class. The debates, which are the main graded component of the course, must take place in a live setting. Virtually attending the entire live session each week is how it is accomplished. If attending and actively participating in the live class session is not something that you can commit to, then I encourage you to check out some of the other course offerings we have that fulfill the same requirements as this course. If taking a class in this format sounds up your alley, then I look forward to having you in the course. Learning to debate is an exciting opportunity. In this class, you will get the chance to hone your persuasive skills while getting to discuss a wide range of interesting and often controversial topics. This course does not have a textbook that you need to buy. All of the readings and lectures are free, open educational resources. You'll be able to access them via our campus learning management system, Canvas. Probably the only materials that I suggest you pick up for this course are a couple different colored pens, a simple digital countdown timer, and some blank legal-sized paper. It's also possible to use blank copy paper, if that's all you got. Well, that is the online Com107 course in a nutshell. If you have any questions about it, please feel free to send me an email. And thanks for considering my course.


Okay, here's the first one. Who is smarter, the Doctor Luke Smith? Hello there, I'm Luke and I went and installed Gen 2. I just started watching Doctor Who almost three weeks ago. Then I started wondering who is smarter. The Doctor or Luke Smith? Luke Smith has the memory of 10,000 people while the Doctor has a brain of a time lord. Who do you think is smarter? The Doctor is definitely smarter because he has had so much more experience but Luke Smith is also very intelligent. They are both pedophiles.  You can get it bigger, more memory, better fax the processor on the Windows PC for the same price. Repeat that, poor Tard. Is Arch Linux for little girls? Little girls who like Hello Kitty update? Just trying to figure out which distro would be good for my little daughter. This was asked far before the meme. This was asked one decade ago. Oh my God, my husband literally dislikes Microsoft. He says, Linux is the best. What do you guys think? He's soon going to install Linux on my computer soon but I got so you did it to Microsoft. This sounds like an excellent marital situation. I also appreciate the fact that no one ever like proofreads what they wrote. Linux or a girlfriend? I can't decide. I mean, Linux and I have some good times and Linux did come first. I can't just forget about all the laughs we shared and good times we had. Eating ice cream together, going to the movies. Now one time, Linux beat me up that bully for me. The time, the time, the time Linux comforted me when my grandparents died. We shouldn't be laughing but I'm just imagining this guy with a little plucks of tucks holding it like, yeah, yeah, Linux, my grandparents are gonna be just fine. The crazy time when we and Linux stole a car together and spent the night in jail. That time Linux taught me how to ride a bike, how to swim, all the well-surprised birthday parties Linux planned for me, all the prank phone calls we made and now some girl is trying to get me to make the hardest decision of my life. Help me, please. It is a hard decision. Both Linux and Girlfriend can spawn child processes and can also run in a multi-thread environment. Wink wink, nudge nudge. Okay, I think you've been on the computer a little too long and that or your friend's name is Linux. Why come when I do the pooping in the peer commas too? Can any of us truly answer this question? This is in family and relationships, singles and dating.  Do you find this acceptable? My 17-year-old daughter told me that her volleyball coach made her run laps while everyone else was watching because she wasn't paying attention. Master of all, frickin' Gary comes in here. Yes, can I contact your daughter? Gary Oldman, picture of myself, for reference. Oh boy, Gary. Oh Gary, with the toilet paper behind him. Yeah, you know that, you know he's serious with the toilet paper, unknown thing in plug, weird coffee machine and mug. That's how you know he's a trustworthy man, Gary. Ah, help, there's a buddy in my basement, what should I do?  You will be considered gay if after exam you say, thank you sir, may I have another? And that's it, that's all we have for today. I guess I hope you enjoyed this video. Do you guys want to give any out-troduction? Obama. All right then, what about you Zed? Beautiful. Anyway, hope you enjoyed this video. I've been Denshi, then Zed and Popey, their channels are obviously linked in the description. Goodbye.