Blueprints In-depth - Part 1 | Unreal Fest Europe 2019 | Unreal Engine

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Its great video, however beware of the pitfalls if you EVER intend on making a multiplayer game or making your existing game multiplayer supported.

Some of his callouts to wrap-up logic from C++ into blueprintPure functions out of brevity is dangerous because it can cause you to rely on singletons or the dreaded "GetFirstOf" paradigm which is a bad practice for multiplayer.

Be sure to think carefully about what you're doing if your game supports multiple players, as the context can vary what is done based on if its multiple local players, one single player + multiple remote players, dedicated server vs listen server.

👍︎︎ 5 👤︎︎ u/EnjoyBrainDmgNFLFuck 📅︎︎ May 28 2019 🗫︎ replies

Nice. Thanks !

👍︎︎ 1 👤︎︎ u/H4WK1NG 📅︎︎ May 28 2019 🗫︎ replies

These videos/talks were all really good.

👍︎︎ 1 👤︎︎ u/SirToxe 📅︎︎ May 28 2019 🗫︎ replies

Good old Hourences. Dude's been making good content since UE 2.0. Very concise and to the point.

👍︎︎ 1 👤︎︎ u/Hascalod 📅︎︎ May 28 2019 🗫︎ replies
Captions
>>Sjoerd De Jong: Welcome to my Blueprint marathon. It is only two hours long. It will be fine. Two hours of hardcore Blueprints. My name is still the same. I am still Sjoerd. I am the evangelist for Europe, been doing this now for I think four or five years. I have been using Unreal Engine for 20 years, started with Blueprint in particular in 2013 I think before Unreal Engine 4 went public. I know that what I started with was we had one single page of documentation on Blueprint when I started. That was, how do I make a door? I started with a tutorial, how do I make a door, and that is it. Then I just started clicking around and experimenting with it and seeing where it takes me. That is usually how I learn things. I just click around, see what happens. It takes a much longer time than if I just read something. But on the other hand, by doing that, I also learn what not to do. I learn to fail. I learn all the things that a tutorial would not tell you necessarily. What we are going to do is we are going to talk about Blueprint in depth. I have made a beautiful little graph here where it says dive into Blueprint and learn stuff and then print string, hooray. That is kind of the conclusion. The idea is to give you an in-depth insight and knowledge of Blueprint beyond the usual topics. This is not about you click here and this is how you script it. It is a little bit about the bigger problems that you can fix in Blueprint. It goes in terms of collaboration, how does that balance with C++, things like performance, what is cost in performance, how do you then counter that? Those kinds of things. That is really the focus of this talk. I am not a programmer. I am an artist designer. I am going to get back to that a few times as well. You need to look at this talk in that perspective. This is not me as a programmer saying, you should do this, this and this. This is me as a designer saying, I went terribly wrong here, here, and here and here, and then a lot of programs got pissed at me here and here and here. Probably do not do that. That is how I am going to speak. What we really want to do is we want to use Blueprint in an advised, scalable, performant, and future proof way. It is not just about making it work. It is about doing as well. Before I start, just for myself to have a little bit of an idea of who is in the audience, who of you uses Blueprint daily or weekly, often? What is the average degree of experience? Who has been using Blueprint for more than three years? How many of you are programmers? That is scary. How many of you are artists? Designers, or similar? We will see how this goes. It is always scary when you do one of these talks. What does the audience already know? Maybe everything is totally obvious. I do not know. It probably is not, I hope. I did this one at Unreal Academy in December for the first time. Halfway in, there is a break. There are a couple of slides halfway in. That is the break point. I might not make it to that break point in time, so it might happen that I will just stop at a certain point, we take the break, and we come back with the rest. Because I just guessed where the break would be. I might have completely guessed it wrong. Let us get started. Before we start for real, there are two introductory chapters. In fact, I had an overview slide somewhere that is going to come in a second that shows you the general layout. But we have an introduction, just refreshing your mind what kinds of systems and features we have in Blueprint. Just so everyone is aware, these are our building blocks we are working with. Then I also want to formalize a little bit of the problem that we have that you might face with Blueprint. We have those two out of the way. We are going to go in depth technical and performance, compiling, etc. I think getting started with Blueprint is easy. For me as well, I just clicked around as I explained in the beginning. It is not that difficult to figure out. It is kind of like a flowchart and it kind of just works. Obviously, you have got to learn this. It took me a few months as well, but it is relatively straightforward. You can learn that. The real difficulty comes in doing this correctly. Even the way we design Blueprint, it is kind of similar to - it makes programming concepts easier to understand as well. All of this is visual scripting. It is designed to make ii accessible. It is really about how to use it correctly. We want to do this for three reasons. We want to have it future proof so you can extend it. Again, you will see some of the mistakes I make with that. I am sure you have all done the same stuff. Collaboration is a topic that comes back often. How do we work in Blueprint, the binary Assets, how do we merge stuff together, what is the advice way forward? Performance is a typical one as well. But because that is maybe not ideal. There is actually a website -- I now forgot the name, but you can Google it. There is a website someone set up in a community where you can post Blueprint spaghetti pictures. It is a website that is dedicated to just that. I took these pictures from there. Credit goes to whoever posted it on there. For example, you could do that. I really like this long, long blue line. That line here, it goes up. You have no idea what is there. But it might be a lot worse. It is kind of like these paintings where you see something on the edge of the screen and your imagination takes over with the rest. It is really well done. That is not that bad. It is just a lot of copy pasting. At least it is clean. I like that every single part of it is commented. That is not that bad. It is just very compressed. It could be worse. You can actually frame it. [Laughter] I really like this one as well. This curl here I really nicely artistic. Google that website and have some fun. Just before we start, just to make it clear, BP means Blueprint. Obviously, Classes means either Blueprint or C++ entities. Native is equal to C++. We are going to switch those terms around, so everyone is aware. Lines mean break of subject. This is what we have got. I hope to get here by the break, have performance covered. But again, the break might be somewhere halfway into performance. We will see how that goes. We start off with these two introduction parts. Performance is a big one. This is technical. Compilation is technical. Runtime cost, ticking, profiling, memory loading, garbage collection with compilation overview and the impact of it, compiled times, casting, recommended workflow, race conditions -- although I only have a little bit on that. Some on C++. It could be longer there, but we are definitely going to cover that. Again, I am not a programmer, so I am going to cover C++ from a designer’s perspective. Then we have some miscellaneous tips. This is mostly here as backup in case I am done early. I need to manage my time, so it is just some random tips. Let us start with just refreshing everyone’s mind. A lot of this is discussable. There are a lot of different ways you can often approach the same problem. You could say C++ is not a feature. You could reasonably say so. But for the sake of trying to give a schematic overview of what we are dealing with from a Blueprint perspective, in a way C++ is a feature that helps the Blueprint workflow. Let us just take that mindset for a second. You can discuss this for a few years if you want to, but bear with me. You have C++. All of this feeds into the system that is Blueprint. You have got Data Tables and Curves. You have got Data Assets. You have got Child Actors, Interfaces, Libraries, Framework, Components, Inheritance. Those are kind of the things you are working with, the building blocks. I am just going to step through those to quickly again refresh your mind. C++ could be smoothly combined with Blueprint. We can smoothly balance functionality back and forth between the two. It is obviously a faster performance which we will get back to later on. In larger projects, obviously better for collaboration. I think most of this is obvious for everyone. Inheritance meaning it inherits from a parent Class. You can do this within Blueprint as well. Again, this is so fundamental to the Engine. Everyone who has been using the Engine for a while will understand this. You have got the framework Classes which means the standard Classes such as GameMode, PlayerController, those kinds of Classes. Those are present within the Unreal Engine. It is a tool in your toolkit as well to work with. We have got Components, and when I say Components, I specifically mean a Blueprint Component. I do not mean a light or anything else. Let us just focus purely on Blueprint right now. You could have a Component that holds some Blueprint functionality or C++ functionality that is added to the Object and to the Actor and it gives some specific results. For example, this is from my own game that I did a few years ago. We had a temperature system, so some items and some Meshes had to offset the temperature. For example, the crystals were cold, so we made a Component called TemperatureComponent which added essentially an offset to the temperature that you can set to a range, and we did that. That is kind of what we use Components for. Again, a lot of this is discussable. You could argue, yes, but we use it a lot more, or you can have this kind of workflow, etc. But ideally, Components in Unreal Engine tend to be used for specific solutions. They do not tend to be used I am going to have 50 different Components where the Unity approach, that would be more their workflow. It is not typically what we do. You have got Child Actors. It is literally another Actor Class that has been added as a child Actor in another one. For example, this flashlight, the volumetric light beam thing itself and the Light Actors, that is a Child Actor that got added to the flashlight. We will get back to this later on as well with a few examples. It is not that commonly used, I think. Typically again, specific purpose only. Libraries meaning like a Blueprint library or it could be done in C++ as well. That is another one you can use. You have got interfaces, of course, within Blueprint. You have got data tables and curves so you can specify a curve and then read from that Blueprint. You can make a data table read from that Blueprint. I think most of you I hope have done this before, all of this. Otherwise, the rest is probably going to get a little bit hard. Data Assets exist as well. To make a Data Asset is basically just holding a couple of properties and read from that. The tire system uses this by default. Interface I am missing here, which is intentional. Again, you can argue this for the remainder of Unreal Fest if this is correct or not, but it is one way of looking at it. I am trying to just structure it a little bit just to give you a little bit of a feeling what you are dealing with, and you could therefore argue obviously C++ and Inheritance is the absolute foundation. Framework would have a supporting role, Libraries as well. Components, Child Actors tend to be more optional in light of what we just saw, etc. Just trying to structure it a little bit. Let us talk a little bit about the main issue. Once you are past the initial hurdle of learning how to work with Blueprint, you are going to hit very specific problems, especially if you are not a programmer. Because you have never had to do that before. I hit those issues too. If you are a programmer, you are probably more likely to think of the bigger picture and what is my architecture going to be like, where does my certain functionality live? How would that scale in the future? How do I make sure I can keep that as buck-free as possible and how can I maintain it? You are going to start thinking of that. But if you are an artist so you have never done this before, you will not think that probably. You will only start thinking that after you have failed a couple of times or someone screamed at you in the office. That is where. I have this example of a door. At some point, I got this sent to me. They built all of that. I did this. It is a super simple example, but you have been in these situations before. How do you make it easy to understand? How do you make it clean but still powerful? How do you get that balance right? I had a number of steps here. Did I do everything as clean and as few steps as possible? Those are kind of the questions you should ask yourself if you look at this. If someone else would take over your work, would they understand it reasonably fast? Do I have a logical distribution? Does it simply make sense, what you have done, or is it just bizarre? Did it take casting and memory and performance consideration into account that we are going to discuss later? If ever you want to grow this, is that doable in a reasonable way? Those kinds of questions you should ask when you build a system. Again, especially I know from a designer’s background, I never asked those questions until it went wrong. I had this Swedish door. I live in Sweden. Classical Swedish yellow door. This is a very theoretical example. Just bear with me, but it illustrates the point. You are going to say, I want to make a door. Make a Blueprint_ RegularDoor. You have a door. Easy, right? There is a trigger, you walk into the trigger, the door opens. We made a door. We start placing it in the Level. Then someone comes to the conclusion, actually, there should be a double door too. We duplicate the first Blueprint. Now we have two Blueprints. They are exactly the same. They are duplicate, but in the second one, we make two door halves, but it is still the same figure. It is only two doors, right? What could possible go wrong? It starts fine. Then the problem is, someone wants revolving door and a garage door and an elevator door. We start duplicating it again. Now we have five duplicate Blueprints with some changes to it. It is maybe not ideal. Someone comes to the conclusion, let us make a parent Class in Blueprint called EnvironmentObject or whatever we are going to call it, Doors, anything you want, which has the main trigger functionality. Then there are child Classes under it which would be the actual doors, the variations on that. Maybe the door has to be destructible, so we have a Component in there just to handle that, perhaps. The problem is, as the game goes along -- because this is what you do in your first prototype. This is a few months in, and it gets worse. Then someone, for reasons we will get back to later on, there probably should be some C++ Classes above it. Now we have more locations where functionality could reside that has to do with opening the door. Then perhaps you do not just want to walk into the trigger. Perhaps you want to get close and then play an animation or press a button or something more than just walking the trigger, right? You have got the whole player and player control of things comes in and has functionality for the door too. You want to have an Animation Blueprint that is related to it because you need to play some animation for opening the door or whatever, right? There is more stuff. You need a HUD Because you need to display something about yes, you can open this door or not. We have that coming in. It gets worse, because someone wants to have achievements, how many doors you want to open and stuff, so that has to keep track of it too. Then there are a lot of different Levels with a lot of different doors. All the Level Blueprints might have references or some functionality related to opening doors. For example, if you open this door, a monster should spawn there or something. Somehow, you need to link that together. Then there is AI. Then you need all of those Classes, and then there is probably NPC, humanoid, enemy, and then there is a solider or something, etc. Again, it is a very theoretical example, but it kind of paints the picture of what happens over the course of game development. It gets worse because someone has weapons, you need to be able to shoot the door as well. Eventually, you have got all of this that could potentially hold functionality relating to you opening a door. If you started this idea with, I am going to do this, probably you had an issue. That is exactly what an artist and a designer is going to do, typically. I would have done that too. I would have done that. That is the goal of this talk. You want to keep things as simple as possible by having enough complexity. If you can manage that, you are good. There is a very golden line somewhere between keep everything as simple as possible. Otherwise, it is too difficult to maintain and understand. But do not skip out on using advanced features. But do not use advanced features for the sake of using them. There is this very fine line between them. Do not over-complicate when you do not have to, but do use advanced features when it simplifies things. The functionality has to be scalable. Try to be as agnostic and as justifiable. Of course, sometimes it does not make sense. You just do it. But it depends case to case. Performance and stability should be taken into account from day one. You have got collaboration on Blueprints is also a challenge sometimes, and that is helped tremendously by designing it with the right architecture from day one. We have got a merge tool, but it is not meant for day to day usage. Having the right hierarchy and distribution of functionality is going to help you there too. This would be a theoretical example of what a car could be like and what the distribution of functionality could be like. Obviously, we have got an Actor at the top. You have got a Pawn. There is a Wheeled Vehicle, standard Class, but then you would have maybe your vehicle Class, your particular car Class. There is a Blueprint Class that comes directly from that. We are going to get back to why specifically I am advising that, and then a Blueprint Sedan. The headlights should probably be a Child Actor perhaps, because it is a set of different components together that are going to be used across different vehicles. CarEngineValues might be a data table, so you can easily tweak that stuff. There are probably some general libraries in use somewhere in there. The VehicleMovementComponent is a standard Component, but that would be a Component. There is a Data Asset for the tires. That is also a standard part of the Engine. But this kind of gives you the idea. Build up that architecture. Let us start doing Editor things. I will switch to the Editor back and forth as I am doing this to demonstrate some of it. Again, a lot of the examples I built in the Editor are very strange by themselves. They are kind of just there to illustrate what I am saying. Obviously, the best case scenario would be if I have a full game that we worked on for two or three years. In a realistic scenario, that is kind of difficult to simulate. We will have some theoretical ones in Editor. In general, I think performance is really important even if for whatever reason you do not feel it is going to be an issue. Working cleanly is good anyway. It is going to help the performance. It is going to help with other things too. Blueprint is slower than C++. It is not slow at all. The most common reason that we see that people move from Blueprint to C++ is not speed. It is typically workflow and collaboration much more so than performance itself. There are of course exceptions to everything I am saying, but in general. Nonetheless, there is a bit of an impact of Blueprints. Kind of they are 10 times slower-ish, but it really depends a lot on what you are doing. It is difficult to put a number on it. It depends on the project, it depends the hardware. As Nick mentioned in a keynote yesterday, we are looking into experimenting with different virtual machines for Blueprint. We are expecting a further speedup of Blueprint performance in the future. I have got a graph that compares the different performances of Blueprint, a couple of different states I am going to get to in a second. But before we go there, a couple of reasons. The first reason -- not necessarily in the right order -- but the first reason you could say why Blueprint could be slow is simply executing large networks of nodes. Because performance cost comes from the connection between nodes, not what the nodes actually do. There is a cost to them, but it is not necessarily Blueprint-related. Anything that is node heavy or logic heavy is for that reason expensive because it is a lot of connections. If you have got this example over here, it is very simple. Print String, all this does the line trace. This is 100 percent equal in performance in terms of Blueprint. It is not 100 percent equal in performance across the board, because this essentially triggers functionality in C++. But the act of triggering that via Blueprint is a line. It is equal, and that is really important to note. Related to that, anything that is related to quick loops tends to be relatively expensive. With quick loops, you have a lot of connections looping, simply. Anything related to quick loops is on the expensive side. Anything that requires iteration of large numbers of Actors is on the expensive side. I have seen many examples of where someone does, on every time they press a button, they do Get all Actors of Class or something. Please do not do that. Please cache the result or something. That is expensive too. Then of course, ticking. We are going to look into ticking extensively. That is typically the most common cause of performance loss, extensive use of ticking. For everyday usage, you are not likely to experience any slowdowns. I am not telling you, please never do a wire loop. You have to judge this case by case. But eventually, if it is a long project, large team, etc., over time, it might add up. Blueprint is always executed single threaded. It has a default of a million, which translate to 250,000 in reality, instruction execution limit per tick and for all Blueprints combined. You can set this in the project setting. You can actually set it to maximum loop iteration count. I do not think you should change it. I am just saying it is there. You cannot hit that limit unless you are really doing stuff in very sub-optimal ways. For that reason, you probably really should not change it. You probably really should not hit the limit either. If you hit the limit, you will just get an error that says infinite loop detected or similar. A Blueprint in itself does not give any significant overhead. Just making a prefab essentially with Static Mesh Components in there, it does not give a measurable impact on performance. You would have to go very far for that to eventually start impacting you. Generally, that is okay. Also, we are going to look at the comparison now. Before we look at the comparison, note that there are three different ways of doing this. You have got Play in Editor, you have Dev Play. Dev Play is my improvised name for meaning you start the game but without packaging it. Shipping Play is you package it and you play it. Let us take those three different States. We have got a very simple test Blueprint which again is theoretical. It is not necessarily always representative of real life, but it does a random calculation and loops that around very quickly. On a timer, every one second or whatever, it does a lot of calculations looped. Trying to string the Blueprint. That is what we had in this particular test. It is a slight difference between red and blue. In C++ to Blueprint, you can see Blueprint gets a little bit expensive. Blueprint is the red line, confusingly enough. I am sorry. It gets a little bit more expensive than the blue line here at the bottom. But this is both in Play in Editor. Because the next one gets more interesting. This is without C++, pure Blueprint, shipping compared to Play in Editor, compared to just running the game. You can see Play in Editor is way more expensive. When you ship the project, when you package it, it is half the cost of that one in the worst case scenario. Again, this is a theoretical test. It does not necessarily reflect on reality. But it gives an idea of what you are looking at. If you were to then compare this to C++ here, you can see this would have been Blueprint, the blue line here. C++ would have been here at the bottom, not suitable for this scale. There is a difference. It is slower, but as mentioned before, it is not necessarily slow, just slower. Again, when you profile this, really pay attention to just how slow Play in Editor really is performance-wise. Let us really look at ticking, before there is a lot to say about ticking. It is typically the number one reason for performance loss. Tick itself is not the only thing ticking. A timeline would be ticking while it runs. Stuff like Mouse X or one of those kinds of things, those kinds of inputs that are ticking. In Animation Blueprints, the update animation is essentially ticking as long as that thing is active. In UMG, if you bind something, it is ticking with a couple more of them. Now the obvious advice first, please do not do it much. That is the simplest advice, but it is true. If you are going to use ticking, make it a deliberate decision. Do not just do it because it happened. You have to think this through. In 80 to 90 percent of the cases, you do not need to use ticking. You can also disable ticking on a Blueprint by default, by the way. In the Project Settings -- I forgot now what to type here. I think you can do, Can Blueprints Tick by Default -- you might want to disable that just to make it even more deliberate. If you have people in your team and they actually have to enable ticking for that Blueprint, so it is a conscious decision, do I really need it? Yes, I am going to say yes. Now, timers and events can take care of almost everything. Simple example, we have a timer, it loops this print string. You can do a lot with that. You can offset the time with a random float in range if you have a lot of instances of this Blueprint to distribute the cost. Instead of having, for example, in my game, I had 100 different items or so per Level. All of those 100 items are on a timer, a couple of different times. I do not want all those 100 items to loop at the same time, because you have got a spike at the same time. Random float in range could help distribute the load a little bit. If you do it Event based as much as possible -- here is a simple UMG example. Instead of doing bind, we did a bind on a text field. This is essentially ticking. Make sure the text in UMG only updates on an Event. You can do this across the Blueprints. Event based is always the best. You can turn off ticking in a Blueprint itself as well, or you can change the tick frequency, the interval. If a Blueprint does not actually use ticking in its graph, having this enabled or disabled does not make a difference, is what I have been told. But some other people would contend that. If you leave it enabled, it does show up in the ticking list, but it does not seem to bear a performance cost. I will show you later on how to display all the Actors in the Level that are ticking. This would pollute that list a little bit, because it would just crowd the list with random stuff. To be good, you might turn it off. You can have building conditions that limit how often when ticking is active. For example, you could do One Player Pawn, Get Distance To, so you only do ticking if the player is closer than X number of units to the Actor. You can simply do that and it might be a benefit. Similarly so in the next one, you can reduce the tick frequency on distance as well. Go to Distance To and gradually reduce the update rate of that Actor, of that Blueprint the further away you get. It is just those couple of nodes. You could obviously automate some of this in C++ as well via function in there. When you face away, you have this thing called in Blueprint, Was Recently Rendered, that you claim number figure out if you are seeing an Actor or not. If you know you can see it or not with that thing, if false, then turn off the ticking or slow it down or whatever you want. That is another simple one. Again, it is really just a few nodes every single time. Often, you can split the logic from the visual effects. This was my game from a few years ago that some of you might remember, Solace. We had an ocean in there with a bunch of islands, so every island is obviously surrounded by an ocean. The ocean had rising tides. The ocean was made by essentially a Blueprint, and the Blueprint was a giant Mesh plane, which is the water surface and a couple of particles and other random things that touched. Then there was a box underneath, a collision box which acts like a Water Volume and a Post Process Volume and such. The surface, the Mesh itself continuously looked at a float value for the time or the tide. It read a value, and based on the value, it would change its position. You looped between A and B, and you would set that. That was really, really, really, really slow, because it turned out that moving a gigantic trigger box across the entire Level and doing an overlap check on everything in the Level is not super fast. My solution was, often there is a very particular thing that is heavy. Ticking itself is not necessarily bad. My point is, sometimes it is just one particular part of it, so take that one particular part out of it. I did the updating Volumes, I put that on a timer. That is the logic from the Volumes, so I just set Actor location. That is the timer now, but the visual functionality remained unticked because there was barely any cost to that. Again, judge it case to case and try to split it where possible. The same goes for anything that is animated in general. It is a bit of a simple example, but I have got this rotating Mesh. There was a code on here, 06. It rotates. It is a simple one. You would not probably have done this in Blueprint anyway. But the point is, if you want to animate a basic animation, if you can do this in the Material, then it is done on the GPU, not on the CPU. It is not done in Blueprint, and it almost always executes faster. This is faster than the equivalent of doing that in Blueprint, almost always. Whatever you can pull off doing via World Position Offset in the Material, do that. Obviously, it is not going to help with collision or other things, so there are limitations to this. But what you can, please do that. In fact, the next step is 07, which is what we have over here. In fact, I can just show you in the Editor. I have got this little Blueprint here with a cube. If we play this, the cube goes from red to green. But if I change the option here, Use Parameter -- I will show you in a second what I actually did - and I play this again, it also goes from red to green. It is the exact same thing. One of them is driven by Blueprint. The other one is not. Here is the Blueprint. This is your parameter switch. If it is true, it makes the Dynamic Material Instance, and it has a timeline. This is ticking, and it changes this with the timeline. Instead of doing that, you could have done that. It does not do this at all. It just makes the Dynamic Material Instance and then the Material takes care of the rest without even being triggered by Blueprint. It simplifies your Blueprint too. In the Material that we have over here, if parameter this, it simply does that. There is a time, I divide the time, and it just runs. It handles it. The moment it enters the world, the time starts being taken into account and it automatically fades from that to that. That is it. You can use this for footsteps or something. For anything that has a set length of time, that simply will play its animation, its fate, or whatever it is meant to do without you having to do this for your Blueprint. Again, that is almost always faster than stripping that. Or again, very simple advice, just do it in C++, which is true. But before you do that, please profile it first and really justify it. Why are you really doing it? Because often again, it is not necessary to move it in C++. Now we have got a couple of different ways for profiling and debugging. There is actually a lot to say about this. This is a relatively short chapter, so I will just skip through a couple of these. I will start with the obvious one. I think the Visual Logger and those kinds of features, which I will get back to in a second, I do not think they are maybe that well-known or that much used. I never used them in production either. I knew it was there, but I did not see the use for it. But I think it is really cool. I want to just highlight that. First of all, as you have probably all figured out, you can visualize Blueprint as it runs. If you are playing in a game, you can see that happen. I am sure you have done this before. As you are playing, you could do, no debug object selected, third-person Character, and I can see this happen. I can watch values as well, which is the next slide. If I right-click something, on this one, watch this value. It will print it above it, and I can see it as it happens. This is really nice to debug your logic and have an idea of where the flow goes to. When you watch the values, in the Blueprint debugger window, you can watch all of them at the same time, which is quite nice. You can have a general output of everything you are doing there. You have a Window, Developer Tools, Blueprint Debugger. In the Watches, you would see all of the watches combined. You have a general view of the whole thing. That is quite nice. Again, I knew it was there, but I never think of it while working. It was actually a very useful tool. You have got a Visual Logger. How many of you are using the Visual Logger at least once a year? That is about 8 percent or so of the audience. That is what I mean. This is a nice tool. I like this one. I always forget about it when I am working. It is a nice tool nonetheless. This is in performance 8. The way it works is that you have to make a Blueprint or within an existing Blueprint. You have to enable Visual Logging. On begin play, Enable VisLog Recording, yes. Then on tick, you would have this set that records it. There are a couple of random tests. But I take a Health variable. It is just a variable, and I append it with text so I can understand in the Visual Logger what it is. Health is X. I do a VisLog Text action. There is a VisLog Box Shape, VisLog Location, and a VisLog Segment. Those are the different ones you have got, so you add those to it and essentially populate the properties. That is the text it is going to be logging. You can log a shape. This is a box shape based on that location with this shape. This is the VisLog Location. It simply stores the location itself directly and will automatically give that a marker. We have got a couple of other things here. That is it. You can add this in any Blueprint you want, and then when you run the game, you can go to Visual Logger. Again, Developer Tools, Visual Logger, that window there, play. As you can see, it is recording that. Let me just jump a few times. Let me stop that and stop that. What happened now is you have the Actor you were recording in here. This might be hard for you to read, but there is says health is 998, so you can see over time the health is now 587. It made the health tick gradually goes to 0. You can store the variables and see them over time, and you can see where the position was as this happened. That is debug. That is my simple little test, but that was my player running through the world. For example, you can enable this on all of your AI and see how your AI was navigating the world as they were trying to locate the player or whatever they are trying to do. You can have a visual representation of all the variables you marked and the positions of things, which is quite nice to get an idea for what is happening. You have got the Stat window. Obviously you just type "Stat Game." This also tells you how many things are ticking. You have got a few things in there. Blueprint time is interesting. The tick time also shows you there are 19 things here ticking, and the ticking cost of a lot of things. In fact, with the ticking, what you can do is you have a command, dumpticks, and that will give you an output of everything in the World that is ticking. That is very good to do. If you type that every now and then, you keep track of what in the world is actually ticking. You can then go look into that and see, okay, is that justified or not? Literally, just type in here “dumpticks." In this very simple Level, it is not going to do much. But it just outputs you. It is this one here. This is the ticking group it uses, etc. You have that idea. Then you can go look them up. You have the regular profiler, of course, which is quite precise in the sense that it can really show you, look, it is this particular Blueprint, and we have got these Blueprint functions or things in there, and they take this much performance per. I use this one a lot in development. You can actually run automated tests, which again is a thing that is not necessarily well-known. It is also rather strangely implemented, requiring a very specific naming convention. But if you do everything right, it will automatically appear. You can do a functional test in code, of course. But you can actually have a Blueprint functional test and have that be automatically recognized by the automated test window if you name it in a particular way. I have done that. It was 09. I have made this thing here. I made first of all just a test Object. Here is the test Blueprint. It does not do anything. It is meant to be a door. There is a trigger box. There is a door. It is for a test. There is nothing in here. It just says, if the trigger box is overlapped, it says bool is through. It is just for a test. What we are trying to do an automated test on are my triggers of my doors, can they be activated by the player? It is a very basic test, but it illustrates it. Then you have a second Blueprint, which is the functional test example. That is Parent Class Functional Test. By having it as functional test, you get two unique events. One is called Event Prepare Test, and the other one is called Event Start Test. Event Prepare Test is whatever is has to do before it does a test, obviously. I am spawning the door Blueprint at this location. I remember which one it is. Then I spawn a Character, just a regular Character, at this location, which happens to be inside the trigger box of that one. Then I run the test, Event Start Test, and it is going to check, does the door, the bool of that door, is that true? If yes, then the door is being triggered, the trigger works, and we finish the test. I can output a string here that says, Test successful - Door activation status is true. Otherwise, it will fail, Test Result failed. Doing it like that, then very strangely, you have to make a Level called FTEST_ or it does not work. You put the Blueprint in that Level and you save that. If you then go to Developer Tools, Session Frontend -- in automation, we would then have projects, and we see our functional test that we made. That is all Blueprint. We can then enable that and we can say, please start a test. That automatically runs to that Level, and it says the test was successful. You can see here too the test is successful. You can have a series of these Blueprints or one Blueprint that does a lot of different things in the same step. A little bit of a weird setup, but again, I just wanted to highlight that, because I have not seen anyone do this. Let us go back to the Level we had. One second. Then we have got memory and loading. This is a really, really big one. There is a really fundamental thing in there that I realized way too late. I really wish someone told me this the day I started, and I took years. Blueprint is fundamentally different than C++ when it comes to loading and memory. Blueprint is content. C++ is C++. It is completely different, and you really have to understand that or things are going to go wrong. When you have C++, all the C++ code will be loaded on boot. You start the project, it loads all the Classes in C++. Blueprint is only loaded when it is used. I have a slide here. It is crucial to understand. C++ loaded on project boot, but content, which includes all the Assets including Blueprints is only loaded on an as-needed basis. If C++ references content, that content is loaded on boot as well. Here is an example. There are two different Levels here. Both of those Levels reference Blueprints. We are running the reference check on the Blueprint. There are two Levels referencing the Blueprint. That means this Blueprint will only be loaded if the Level is loaded. That Blueprint, in turn, references a Mesh, which references a physical Material, a Material, and a bunch of Textures. If this one is loaded, that one is loaded, that one is loaded, that one is loaded. That is content. It loads it as it needs it. I did not know that, so I did that. This the reference view. Just to make sure everyone is on the same page here. If you have anything, you can right-click Reference Viewer, and then you see what reference it is. This was a kind of bad example because it is not showing a reference. It is my basic Blueprint. Let us find something else. Let us take the performance test one, because it is going to say it is going to be referenced by the Level. You can see that references the door on that side, but on that side, it is referenced by the Level. You can change the search depth, which is not going to do anything here, because nothing else uses it. But you can bump up the search depth and see the whole network of what is -- that one uses also a cube. That will probably use a Material. That uses a Material. That uses a Texture, then, I assume. Yeah. You can kind of see how the path is going to flow on. Now, this one is not even the full view. I had to span it over my two monitors. One is above the other one. I had a giant resolution, I zoomed out as much as possible, and I think I Photoshopped, because I think somewhere in here, if you see here, the grid point here is messed up. That is the Photoshop copy paste of two pieces together. You can see this is the center point. That is the center Asset. You can imagine what is above it, and you can also see how the line continues at the bottom. It is terrible. Do not do this. I figured I can just reference everything, right? So I did that. Any form of referencing between Blueprint and another Blueprint will also load all the content with it and will also load the other Blueprint. Super, super important. If you do not control this, it is going to get out of hand, especially towards the end of the project. If you cast, it is going to get out of hand, because the casts are also references. We are going to get back extensively to casting in a bit. It ends up like that. This is site map, just to make sure again everyone is aware of what we are doing here. Right-click not reference viewer, but Site Map. Site Map shows you what is loaded. You see all the things that are referenced and loaded for that Asset. The functional door test example takes 660 kilobytes total information including the Mesh - oh, that is the Blueprint, sorry. The Mesh is somewhere. The Static Mesh took 487 kilobytes, etc., for the total sum of it. I did that on that above giant Blueprint, and it kind of looked like that I love how optimistic it is or it tries to manage your feelings, because here in the top, it says Item Standard, which is my Blueprint, at least 1.1 gigabytes. I like that it says at least. It just gave up. Again, kind of do not do that, maybe. Let me get back to this in a second as we go over that slide, because it is a very applied example of that too. You need to plan ahead in how you will organize and manage the references. Please think of this stuff. Prevent Blueprints that reference a huge number of especially large Assets. Try to split it up, have Child Blueprint Classes under it, for example. Here, this is how I started my project. I said in my project, I am going to have a pipe you can pick up, I am going to have a rock you can pick up, a plant, and I think it was a can. Four things. What could possibly go wrong? Let us make a single Blueprint that we call item. In that one item, let us make a function that sets a bunch of variables. Essentially, if this is set, what we do is we say, it is this heavy, it has this name, it has this whatever. Then we reset a couple of things. It was a couple of pivot point things. That is not the right term, but you get the idea. Reset a few things, and then I set the new Static Mesh. That is it. I did that for 4 things. I did that arm 4 times. The problem is, by the end of the project, I ended up not having 4 items. I ended up having 40 or so. I ended up having this giant switch, and the whole thing got out of balance. I ended up referencing every single one of those Materials, Textures, all the particles, all the sounds that were unique for every item, which looked like that as well, as you have seen. Here is what you should do. This is the advice way forward. The best technique is to create a clear hierarchy with rules in place for where the Asset references live, which should look like this. You have every key Class is defined in C++, all of them almost. There is always a Blueprint that is then inheriting from C++ Class, and potentially another Blueprint in turn where it makes sense. Content is ideally referenced primarily in the third step. It looks like this. I have this overview. There is always a Parent Class. That is the C++ one. There is then the Blueprint Class, which in my item example would have been C++ InteractiveItem, Blueprint Interactive_Item, and then the specific ones, Item_Pipe, Item_Bucket, Flashlight, etc. That would have been what I should have done in retrospect. By doing so, and by making the C++ Class above it, you always have that present. Even if there is nothing in there yet, at least you have got the architectures in place. It is going to make it easier later on to move things to C++ if needed. That is a topic we will get back to later on. By having the content references in here in separate Child Blueprints, if a Level needs a pipe, it will only load this Blueprint. The functionality might still be here, but the content references, the Materials, the Meshes, they are only in this Blueprint. They are only going to be loaded when the Level needs that particular item. Right now, when I load a Level in my game, it loads every single item you could possibly have and all the Assets along with it. Libraries. If you have function libraries or macro libraries, any kind of Blueprint library, we have got a similar kind of challenge there. If a single function of the library is used, the entire library is loaded. Please be aware of that. If you have a reference in any one of the functions within the library, that reference is brought along. I have seen an example about a year or so ago where there was -- you have a main menu, and then the main menu was completely separate from the game, as it should be for these reasons. But it was one particular function that was used from a Blueprint function library. It just loaded something related to the menu. There was something in that function library, like I do not know, find sound for menu or something. Whatever. But somewhere else in that same function library, there was a reference to another Class, which had the reference to another Class, to another Class, to the entire game. Eventually, it would load the whole thing. The moment you would load that main menu, it would load one gigabyte of extra data for the act of doing that because of that one reference to that function library. You really want to pay attention for that. For example, in this example, this is not optimal. But it could be. It depends again how critical it is. To be entirely clean is not optimal. A very basic one where it says, here is a function, Get Components by Class, get all Static Mesh Components, find all the sockets with this name in there -- that is kind of a weird one, I know. Ignore that. Then spawn emitters at that socket. I do not know why I want to do that. But ignore that. The point is, there is a reference here to an emitter. That means that emitter will always be loaded whenever any function in that entire function library is used. This would be more correct, where the particle is a variable that is brought in. Because then you specify what particle to use where you use the function and not in the function itself. Those kinds of things. Game Modes help for this as well. The whole point of Game Modes is to kind of help you separate the two, to make a clear break. Okay, so this is all of that, and this is all of this. We do not have the references going back and forth. There is dynamic Asset loading, which you can also do in Blueprints. I can just show you in the Editor. This is 11. Here is all this stuff here first. You have got this, for example. That would be the normal way of doing it, you just do, Set Static Mesh. That is now a hard reference. You could do an Async Load Asset. Then you have the reference to the Mesh there. You cast it to a Static Mesh, in this case. Then you set the Static Mesh from that thing you got from the Async Load Asset. That will load the Asset on the fly as you need it. There might be a small hitch there. That is something to be aware of. If you then look in the reference viewer, you see what happens there. You get this pink line. That is the soft reference line. It also distinguishes it in the reference viewer. When you have soft references - and it is the only way forward when you have a lot of configurable parts, so different parts - you can use maps. Again, that was the one we had underneath here. We have a soft reference example. Full screen here. Essentially, you can have a string that is touched to the Asset. Therefore, you can always find something. Essentially, it is like a table. You can say, find me the bucket. You just say, look for bucket, and it finds you the Mesh associated with the bucket instead of having to look for the actual bucket itself. That makes it more configurable. It makes it easy to manage. If ever you change the bucket, the Mesh itself, maybe assign a different Asset to it, you would not have to change some of the logic either, because it would have to try to find that Asset in there. It does not even work. This is the better way forward. You can look for a keyword, and it will return you the Mesh associated with that. That is a map Asset. Also, just to point out a different topic kind of, but loading times in the Editor are way different from the final package project. Again, you cannot look at that. Also, in the Editor, there is actually in the Config file, I think it is the game .ini file, I think. I am not 100 percent sure now. You can say recompile on load. You can actually turn that off. Because by default, when you start the Editor, it is also going to compile the Blueprints. In some cases -- this is rare, but I have had a case like that where something got corrupted in the Blueprint, it will crash the Editor the moment you load it, because the crash happens on compile of Blueprint, and the Editor compiles the Blueprints on load, so the Editor does not start anymore. This would fix that. It might also speed up Editor boot times depending on project setup. I will do this one quickly and then we will end part one, move to part two. Garbage collection is not a very long -- there is a lot to say about this. I am keeping it fairly straightforward. It is obviously the process of collecting and removing any Objects that are no longer required. We have got a test Level of that. Because whenever you destroy something in game, it is not immediately removed yet. It is simply hidden from the world. It is simply marked as, this should no longer be there, but it is not actually removed from the game just yet. In order to do that, we would have to iterate through everything in the world, and then say, yeah, that one should be gone. We cannot do that all the time. That is expensive. That is the garbage collection process. At regular intervals, the Engine is going to look through everything and say, that, that, and then that, let us move that. That is garbage collection. It is somewhat expensive because of the iteration it has to do. Often, there is no need to think about it, but I just want to explain a little bit. Again, if you are not from an engineering or programming background, you might not have considered this all too much. What you can do here is there is a stat called stat garbage. In fact, I have a Level here. Simple setup. These are going to spawn things, a lot of it. Worst case scenario, a lot of it. You could use this to see what the impact is going to be on garbage collection. Every now and then, it is going to hitch, because it has spawned a lot, and it is remembering all of these cubes still. It eventually has to remove all of the cubes. You can change this and you can use the stats to see what the cost is. But you can change it just to test it in Project Settings. You probably should not if you do not know really exactly why you want to do it, but just for the sake of demonstration. In Garbage Collection, which I forgot what it is named. You can change the time. Because by default, it is every 61 seconds, I think. Engine - Garbage Collection, Time Between Purging Pending Kill Objects. Let us do that. Let us look for purging, because nothing else is probably called purging. There we are. 61 seconds. If I make this say 10 seconds and you run the game, you can clearly see what would happen. At some point in 10 seconds, we should get a hitch. But the computer might be too powerful. There. That was a hitch there. That was garbage collection. You can tweak it. If you are doing non-games, there have been quite a few cases that we have noticed where it makes sense to tweak this value. If you are in games, I think you should be much more cautious. For example, if you work in film, you do not necessarily want this to happen every one minute. You might be okay just to let it run for an hour or so, depending on the memory and what you are doing. Also, you can cluster. In Blueprint there is a setting. Every Blueprint, there is a setting that says, Can be in Cluster. But in general, everything related to garbage collection is complicated, so if you are running into problems with this, if you are doing a lot of spawning and destroying, you should probably really involve a programmer and look through this properly. That is it. Let us take a break. Everyone good? Thank you. [Applause] ♫ Unreal logo music ♫
Info
Channel: Unreal Engine
Views: 85,671
Rating: undefined out of 5
Keywords: Unreal, Game Dev, Epic Games, Game Development, Prague, Game Engine, Unreal Fest, Unreal Engine, Unreal Fest Europe, UE Fest, UE4
Id: j6mskTgL7kU
Channel Id: undefined
Length: 55min 6sec (3306 seconds)
Published: Mon May 20 2019
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.