Bolt / Unity Visual Scripting Recommended Practices

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello my name is jesse kraft finch i'm a programmer and game developer located out of western massachusetts where i run a game development company called gorilla tactics i do contract work for large companies to help them finish features and meet deadlines and i do custom projects for individual clients i've been using bolt for several years now on three commercial projects and several personal projects and this presentation is going to be basically me sharing my recommended practices for using bolt i want to be clear that these are not necessarily the best practices i think it's arrogant to say that something's a best practice and i always think there are multiple ways to achieve the same goal based on your project needs these are simply the ways that i have found and recommend that you use bolt to get the best experience with it in this presentation i'm going to assume some knowledge of bolt but in case you don't have any i'm going to give a quick overview of what it is and how it works and then dive into the details i'm going to go through this pretty quickly so if you could hold any questions or comments you have until the end we'll have more than enough time to talk about it afterwards at its simplest bolt is a visual graph editor that means it's similar to the vfx graph and shader graph it's going to try and turn the experience of coding in text to one of dragging and dropping nodes on a graph and for controlling application flow and input control it works really well when people try and bill it as a entire replacement for programming in a game i'm gonna have to give that a big nope before we really jump into the recommended practices though let's give a brief overview of how bolt works in unity the bolt system is made up of two major components state graphs and flow graphs state graphs are containers they hold references to other state graphs and flow graphs and then also establish the transitions between them flow graphs are where your game logic happens it's where you call methods on your scripts and you actually control what's happening in the game a flow graph will be where you're listening for input and determine based on the input where you're going to go and what you're going to do my first recommendation is that you keep your logic in your code i'm going to tell you why while i play two quick examples of writing the same logic in bolt and writing it in code the primary reasons you don't want to write logic in bolt graphs is that it's messy it takes more time and it's hard to duplicate as you can see here we're just writing a standard add and clamp function but there's already a lot of nodes it makes it hard to read and if you want to duplicate that later you need to copy and paste the structure to where you want it to reside if you want to go back and change how that function works you have to change the graph in every location you have that copy and pasted to that's not good when we compare that to writing our logic and code it's much better we can write our logic easily it all resides in one place your programmers are used to seeing that logic in code and you can do more complicated things with it also even if you're referencing that code from multiple locations if you need to change it you're just changing it in the one location that you're referencing it from this is much cleaner and it's why we're going to keep our logic in code and not in a graph just a note on the word logic i've just recommended that you keep your game logic in code and keep it out of bolt i'm now in the rest of the presentation going to sometimes use the word logic to refer to what we're doing in bolt just to be clear i'm referring to application flow and input control logic not game logic game logic stays in code application control and flow logic is fine in bolt i know it's confusing same term different definitions but that's where we are in life my next recommendation concerns where we're going to store the data for our state graphs and there are two options in bolt one is you can have them embedded which means they're serialized with whatever game object they're attached to and the second is to use what they call macro states which simply put means you're saving the data in a separate file i recommend that you use macro states and avoid embedded like the plague that they are the first problem is that embedded graphs are saved with the game object that they're on they're not in a separate file so if you delete that game object you lose the graph here's a real world example yeah that's a pretty sweet graph i got yeah put a lot of work into that many hours well you know i actually need to put this on some other objects so i'm going to delete that and add a new game object and i saved it up wait wait [Applause] the second problem you run into is less dramatic but still important let's say you have a pop-up and it's got a nice embedded state graph shows the pop-up waits for the input and then closes the pop-up this is something you might want to have used in multiple locations you might want to reuse that graph but because it's embedded there's no easy way to copy that functionality to another graph or another object there are two locations where you have to ensure that your graph is listed as a macro and not an embed the first is when you create a game object and you attach a state machine to it it's going to create this default inspector and it's going to default to macro that's great keep it that way you'll be able to select either an existing macro that you have or you'll be able to create a new one and save it in the file that you want right now we're just going to select appflow and now we can open it all right the second place we have to worry about embeds is when we're in a graph and we create a super state a superstate is just a state inside another state that's all it is and as you can see in the upper left when we select it and get some details on it it automatically defaults to embed we want to make sure that we switch it over to macro okay if we don't here's what happens we have my state and inside of it let's just have a start and a transition okay if we copy this it will be identical inside but if we change one of them that change is not propagated to the other that can be confusing problematic etc so instead what we're going to do is we're going to make sure like the game screen we're using a macro if we copy this game screen over here because we want to access it from some other location or whatever your use case is we can look inside and see that this is what we have playing the game after start if we create a new transition here and we go back out and over to this game screen the change propagates to all game screens that use that macro and that's the second benefit one you can't accidentally delete it and two you can reuse the functionality and the states in multiple locations my third recommendation is that you use static strings for both events rather than manually inputting strings into the graph here's an example let's say we want to create a transition between main menu and game screen we have to trigger this transition somehow and a standard way of doing that is by listening to a bolt event we're going to go in here add a node for custom event and have that cause the transition trigger in here we're going to say well because it's between main menu and the game screen it's new game okay anytime an event is fired with new game we're going to trigger the transition however because you're manually entering the string you run into the problems with strings that you have everywhere let's say that there is some other state that you want to transition to the game screen to from we create a transition we create a custom event and now we have to remember what that other event is um i don't remember so i'm going to go back new game okay i'm gonna go back over here new game ah and there's the other problem misspelling happens to everybody and then you spend an hour debugging something to only find out that you put in the name wrong so that's a little taste of why using strings is a bad idea if we go into code in the scene controller let's say we want to trigger an event custom event trigger we give it this game object and the string name new game again we're relying on strings and the human error that goes along with them let's avoid this whole problem and just use static strings to get static strings for both events working there's a couple steps let's go through it one by one first we're going to create a script we're going to call it both events when we open an editor we can actually not have it be mono behavior that's fine but we do need to make it static now let's add our event new game and all that's going to do is get the name of the new game field so now we have that great now we're going to go into our graph into our transition and we want to replace this manual input string with ours so we're going to search for both events and nothing pops up that's because bolt mostly only auto detects mono behaviors so if we wanted to detect both events we need to specifically tell it to see it we're going to go to tools bolt unit options wizard and we want to go over to types once we're down there we're going to add our type bolt events boom generate now that that's regenerated we can go back into the map into our transition and it should pop up boom new game boom now we're accessing a static strip a static string and we're not manually inputting it we can copy this and put it elsewhere so if we have another super state with another transition we can put it in here and also if we're in our code in the scene controller instead of new game we can just reference both events dot new game and that is much cleaner and safer than manually and putting strings into your bolt events my fourth recommended practice is to not use bolt's variable system my standard response when anybody suggests using that variable system is no god no god please no no no no i obviously have strong feelings about this here's how bolt wants you to use variables in the variable system for bolt you have an object store one on that object you have a graph your store graph inside that graph we have our state graph and a flow graph called low store in load store we're calling store controller dot load store which takes a float for our data we can manually add it here on the graph but normally you're going to want to input that in code somewhere so you're going to want access to a variable that you're setting outside of the graph here's the way that bolt wants you to do that you go to the object store one you go to variables and you add store data we're going to say it's a float and we're going to add 3 as our data now once we go into the graph into the load store we can say we can see on the left here that we have access to store data we drag that over here we put that in there we got access that seems nice now it's been a while since i've used this variable system i've been using a different one for quite a while now so i might not remember all the problems with it but let's just go through the ones i can think of off the top of my head these variables don't persist across objects unless you're copying the object so if you have two store objects because you have two stores you may be using the same controller but you want the visuals to be slightly different if you click on store two you can see that the variable is not there anymore store data exists on store one but not on store two so you have to remember what that variable is or go into the graph to look and then add that variable here as well you can't refactor the variables so if for whatever reason we want to change the name of storedata to store info we can do that here in the variable section but once we go into the graph we can see that it's still referencing something called storedata and we need to change that to store info on large graphs this becomes impossible now instead of using the nonsense machine that is both variables we're going to use our own for every object or for every graph that we have we're going to create a variable script we're going to keep the name short for usability so we have our store and we have store vars now we're going to go to our object which references store and we're going to add store vars this is a simple example but it's important to note that if you have any graph which references a store graph you're going to need to have a store vars script on that object this is a simple mono behavior and we can edit it like that all right now if we go into our graph into load store we still have our method call and instead of dragging the variable from the left here we're instead going to access store bars dot data we're going to get it it's important that whenever you try and access a field on a script it's going to check and do get component on whatever object the graph is on so in this case that's why we have to attach store vars to the object that our store graph is on now we have access if we go to our other store we also need to add store bars but unlike the previous situation where we would have to manually add all the variables that the graph needs access to just by adding the script we already know all the variables that needs access to and we provide access to those variables my last recommended practice is to use both events to trigger transitions between states and not tie those transitions to specific controls that's a little confusing in the abstract here's what i mean let's say we have our main menu and our store and we're able to get from our main menu to our store and we also want to be able to get back so we create a transition to go back in that transition we're going to access our store bars which we set up earlier and an x button which i added afterwards we're going to trigger on the x button clicked great now whenever the x button is clicked we're going to transition back from the store to the main menu there are two problems with this one is it is brittle it is tied specifically to the x button if the x button changes or you want to add more transitions you will need to add more here and this gets messy let's not do that the second is whenever this transition occurs based on the button click it immediately transitions between these states it does not provide any cleanup it does not care where in the store or graph it is exiting it just does so in our store let's say that we're in weight player input and we click that button it's not going to go over to clean up store before exiting it's just going to exit and we're going to encounter problems so here's what we do instead of that instead of a button click we're going to listen for a bolt event and that bolt event is going to be exit store this already has one benefit we can call exit store from code we can call it from a graph we can call it from wherever use a tuba outside i don't care anywhere you call it it will transition to the next state so we can have multiple triggers for that which will cause the movement between the states without having to set up an obnoxious number of state transitions the second benefit is that we can control when that event is triggered in our case here we have our wait for player input and then we have our cleanup store we want to make sure that cleanup store gets triggered and run before we actually exit the store this cleanup could be cancelling purchases it could be closing windows whatever it is mopping the floors so in this transition this is where we listen for the button click now when the user clicks the x button or any other input that we want to listen to it will transition from wait for player input to clean up store in the cleanup store we're going to clean up the store we're just going to do a little simple log message here cleaning up not partying and then we're going to trigger a custom event and that custom event is clearly going to be exit store great now inside the store graph it controls when it's going to exit we listen for whoops we listen for the button click it transitions to clean up and that cleanup fires exit store which triggers this transition this allows for a lot more control and flexibility so those are my five recommended practices for bull number one keep your game logic in code number two use macro states not embedded states number three use static strings on a static class for both events don't just type them in four don't use bolts variable system number 4a don't use bolt's variable system number five use both events to transition between state machines don't tie it to specific functionality that's all i got for you today i think if you follow those five recommendations you will be better off than if you didn't we now have some time for me to answer questions if you have a question please step up to the podium and i'll do my best to get through all of them or embarrassingly there will be no questions and we'll just sit here in silence
Info
Channel: Gorilla Tactics
Views: 2,889
Rating: undefined out of 5
Keywords:
Id: hY4QOZwGZ9w
Channel Id: undefined
Length: 22min 21sec (1341 seconds)
Published: Sat May 29 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.