Unity Visual Scripting – Getting Started Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
Welcome to our Unity’s Visual Scripting tutorial. By the end of this video, you will know the basic coding principles and be familiar with the most commonly used nodes. Even if you never coded before, the first steps may be a tad confusing; but trust me – if you stick with it, you’ll get there in no time! If you played a bit with Unity before but new to the world of coding – this guide is for you! We will cover many topics such as Data Types, Lifecycle Events, Logic, Control Flow, Variables, Collections, Loops, and working with Game Objects. Unity 2021 and later comes with the visual scripting solution built-in, so all that is left for us to do is... to start working! In a new empty GameObject, or for any existing one, we add a Script Machine component: in the Add Component menu, select Visual Scripting > Script Machine. This component is responsible for running a script. At this point, change the Source to Embed and click Edit Graph. The Script Graph window should show. Note you can also open it through the menu Window > Visual Scripting > Visual Scripting Graph. In this window, we can view and edit our script, a graph with nodes and connections representing a flow of command we provide to the computer. We already have two nodes, but how do we add new ones? Right-clicking the grid will open the Fuzzy Finder, which organizes the various nodes by categories. If we already know the node we are looking for or the component it belongs to – we can search for it. We can also open the Fuzzy Finder by dragging a line from a node’s port and releasing the mouse. Right-clicking a node allows us to replace it, duplicate it, or delete it. Holding and dragging down while pressing Control on Windows or Command on Mac will create a group – a handy way for organizing graphs. We construct a graph by connecting one node’s output to another node’s input Connecting the green arrows will establish the order of execution for our graph to follow. The Value ports are used to connect values. Each value port has a Type that must be matched when connecting nodes. Nodes missing an input value will recolor their header orange. If the Dim option is active, disconnected nodes will appear darker. Data types: nodes representing single pieces of information. Data is the core of every script; in fact, all that computers do is manipulate and pass data. There are many data types available for us to use in Unity Visual Scripting, but we don’t need to be familiar with all of them; The following are the most common ones: We have two types for representing numbers: Integer is a data type of number values like 6, 10, and -9, commonly used for counting or ordering. It can represent both positive and negative numbers, but not numbers with a fraction like 1.5 or 3.14. To represent these numbers with a fraction, we have the Float data type like 0.5, 7.0, or -2.4; Primarily used for measuring. However, besides storing both positive and negative numbers, it’s not limited to fraction numbers only – it can also represent an integer-like value such as 4.0. We mentioned we use number types for counting or measuring. In addition, we can also use them for arithmetic operations like addition and division or even comparing whether, for example, one number is greater than another. Boolean is a data type with only two possible values – either true or false. It can represent an object state, like whether a door is open or closed or whether or not you gave this video a thumbs up. As we will later learn, we can leverage them to execute different sections of the Graph’s flow. A String is a variable-length text, a sequence of characters like a name or a message. It can contain letters, numbers, symbols, and even emojis. We can use it to print messages to the debug console or display dynamic text in the game’s UI. Enum, short for Enumeration, is a data type consisting of a predefined set of values. For example, we can have an enum with gaming platforms At a given moment, we can only select one of the predefined platforms to play with. Vectors are a group of 2, 3, or 4, Float values. It can represent a character’s position, speed of a moving object, the distance between objects, and more. Depending on the vector type, we can access its float components through the X, Y, Z, and W properties. For example, a Vector 3 consists of three floats accessed through X, Y, and Z. Nodes may have input and output ports; each excepts or provide a value of a specific data type. We can distinguish the port’s data type by its icon. Primitive data types, like most of the types we discussed in this video, are represented with a circle – where each type is colored differently. Object data types, which are data types composed of multiple data types, are represented with an illustrative icon. For instance, a Vector data type is displayed with colored arrows. Besides nodes’ ports, we can add a data type value in our script using a Literal. In the Fuzzy Finder, we can search for the Literal term of each data type to add it to the script and then pass it as an input to another node. Lifecycle Events, nodes triggered by Unity that are usually the starting points of our script graphs. Like any game engine, Unity runs our games by executing a giant loop, repeating over and over to create and update each frame. With Lifecycle Events, we can tap into the game loop stages and apply our custom behaviors. We can also react to various states of a game object. There are many events, such as Input Events and Physics Events; But, for now, we will focus on the Lifecycle Events; those are the events executed during the object’s appearance in the game. As you may have noticed, the Event Nodes are distinguished with a green strip. To help explain the differences between the Lifecycle events, I will use the Debug Log node. With this node, we can print messages to Unity’s Console window. For example, this Log will print “Hello” in the console. The start function is called the first time an object appears in the game. This node is called only once for a given script graph. For example, here is the Log node connected to the Start event. Once we enter play mode, the game will print “Hello” to the console one time. When it comes to rendering, a game is like an animation where each animation frame is generated on the go. The Update event runs for each frame that occurs while playing; It’s the beating heart of our game, allowing us to adapt to the player in real-time. In this example, we connect the Log node to the Update event. Once we enter play mode, the game will print “Hello” to the console on every frame as long as we play. Fixed Update is triggered 50 times a second in a specified interval. We use it instead of Update when interacting with physics. Late Update is similar to the Update event but is triggered after all Update and Fixed Update events in all scripts. We can use Late Update when we want a camera to follow a moving object powered by an Update event. On Enable will be triggered every time the object is activated. For example, this may be used when a level is loaded, a GameObject is dynamically instantiated or re-activating a previously hidden object. On Disable will be triggered when the object is de-activated. On Destroy will be triggered immediately before an object is deleted or removed entirely from the level. we will learn how to compose logic for asking the game about the current state. What makes games unique compared to other entertainment mediums is their ability to react and adapt to their consumer in real-time. Reacting to players’ actions dictates the game to be aware of those actions and the rest of the game’s state. When writing scripts, we can ask questions about the players’ actions and the game state; after receiving answers, we can decide upon them, To compose questions, Unity’s Visual Scripting offers us a handful of Logic nodes. Each Logic node provides a single output, a boolean; Let’s say our game features a car. We can ask whether it has gas, do we have its key, is it broken, etc. The building blocks for asking questions are comparing one thing to another. The fundamental comparison type is asking whether one thing is the same as another. In a car, if the remaining amount of gas in the tank is equal to 0 gallons, we are out of gas; therefore, the car can not drive. In a graph script, we have the Equal and Not Equal nodes; each receives two values and answers if they are the same. Those nodes accept any data type, including numbers, strings, booleans, vectors, and others... When we have two numbers, we can compare their values and ask whether one is greater than, or maybe less than, the other. If the car’s speed is above 55 miles per hour, we are exceeding the speed limit. In a script, we can use the Greater and Less nodes to compare numbers. We also have the Greater Or Equal node to ask if a value is at least some value And the Less Or Equal node to ask if a value is at most some value. If we want to ask multiple questions upon the same values, we can use the Comparison node, which answers all questions at once. Now that we have the basic building blocks, we can combine them into more complex questions. If a character owns a car And has a key, it can drive the car. We use the And node to combine two questions, concluding if the answer to both is true. If a car is out of gas Or has a malefaction, it can’t continue driving. We can use the Or node to ask if either of the answers is true. One thing to note is that when we say either question is true, we don’t mean that only one can be true. If we do want to limit only one of the questions to be true, we have another node to accomplish it. Even if two characters own keys to the same car, it can only have one driver at once. We use the Exclusive Or node to ask whether one and only one of the questions is true. We can use the Negate node to convert a positive boolean into a negative and vice-versa. For example, the Not Equal node is just a shortcut for negating the Equal node. We can combine multiple questions to ask even more complex questions. In fact, the Exclusive Or node is an example for composing two questions. Now that we know how to ask questions and compose them into more complex queries, we can move on to make decisions based on the answers. The Control Flow nodes, together with the Logic nodes, are the heart of coding. They are used for decision-making, guiding a Script Graph on dynamically executing gameplay based on the game’s current state. When we speak about control flow in Visual Scripting, we refer to how our scripts are executed: when different actions are performed and in what order. We previously got to know data types and that nodes have inputs and outputs of data values. We also briefly mentioned that nodes feature green arrows – – each arrow is a Flow. When we connect an output Flow into an input Flow, we tell the Script Graph that after performing a node, it should move on and perform the connected node. We now know the two types of connections in our Script Graph, the Control Flow of execution order and the Data Flow of passing values around. The two flows are not dependent; a node can be used without the Control Flow; we can also pass the Data Flow to one node and the Control Flow to another node. We previously learned how Events are the starting points of Script Graphs; therefore, they feature only an output Flow. They allow us to react to the players’ actions, and in a few moments, we will see how we can utilize the Control Flow nodes to update our response to the player’s actions dynamically while taking the game’s state into account. But first, let’s ask: when do we need dynamic decision-making in our scripts? Let’s say we want our character to unlock a door with a key. We only want the door to open when the character is holding the key. In this scenario, we have a condition and we want to behave differently depending on the condition’s state: If the character lacks a key, the condition is not fulfilled; otherwise, the condition is met. Let’s see how we can implement this in a script... The If node uses a boolean condition to determine which of two output flows to execute. When the condition is true, it will do something; otherwise, it will do something else. This node has two inputs, a Flow and a Boolean. It also has two Flow outputs. This may be the first node you encounter that consists of more than one output Flow. The Control Flow will continue to only one of the branches; According to the input condition the node chooses a branch – one branch for a True value and another for a False value. Speaking of If – if you enjoy this video, please hit the like button! The Switch node is similar to the If node but uses a value input instead of a boolean condition. As a result, this node can have more than just two branches of Flow outputs. When we select a Switch node, we can add, edit, and remove options in the Graph Inspector – each option we add will create an additional output Flow for the node. the Switch node has a Default Flow output; it is used when the input value doesn’t match any given option. The Switch nodes come in three data type flavors: Integer, String, and Enum. We saw how Switch nodes translate a value into one of the multiple Flow branches. A Select node, in contrast, maps such values into other data values instead of Flows. Let’s say we have a boolean; we can map it to 5 when it’s true and 8 when it’s false. A more advanced example will use Select On Integer: in the Graph Inspector, we can add a few options, say -2, 4, and 12. In the graph, we can then connect a different Vector 3 to each option. So now, when we pass one of the configured integer options, the node will provide us with the matching Vector 3. It’s essential always to provide input to the Default port. In addition to Boolean and Integer inputs, there are also Select versions for Flow, String, and Enum. Like a light switch that can turn a light on and off we can use the Toggle Flow node to execute different branches depending on whether the Toggle is on or off. The On and Off outputs flow will execute based on the current state. We can connect Flows into the On/Off inputs to change the state or into the Toggle input to flip it. Immediately after we switch a Toggle, it will perform the Turned On or Off Flows. And in any given point, we can determine the current state through the Is On output Another form is the Toggle Value node; it’s similar to the Toggle Flow in a sense it has an On and Off switch Yet, instead of executing different Flow branches, it will determine the output value based on the input On/Off Values provided. When the Toggle is turned off, the output value will be whatever is connected to the Off input and vice-versa. When we use the On Update event node as our starting point, its Flow will execute each and every frame; we can use the Once node to limit a portion of the Flow to run only one time, ignoring subsequent executions of the script. Using the After output, we can differentiate between the first and subsequent executions. Last, we can use the Reset input Flow to rerun the Once Flow. The last node is Sequence; it will branch out the execution to multiple Flows and perform them in order. It can be used for better organization and readability by splitting a long flow. For a more advanced example, our first branch in the Sequence can be interrupted and stop performing based on an If node. We can add another branch that will perform whether or not the first branch is executed entirely. In short, variables are containers that store information and values. A variable has a name, a type, and a value. The value inside a variable can change throughout the game. Imagine we have a cookie jar and an envelope. The cookie jar can contain different kinds of cookies, be it chocolate cookies or macaroons. An envelope, on the other hand, may only contain letters or postcards. Every container can contain any value as long as it shares the same data type. Therefore, we can’t put a cookie inside an envelope. Well, we can try, but really, no one should. At any point, we can check which cookie is stored in the jar or replace it with another cookie. Each variable belongs to a single Scope. We may want a variable to only be accessible to the current script graph, all scripts in the scene, or even remember its value after quitting the game. In Unity’s Visual Scripting, there are five kinds of Scopes: Graph, Object, Scene, Application, and Saved. Graph variables are local to the specific Script Graph. Therefore, they cannot be accessed or modified outside the script they are created in. Object variables are shared across all script graphs attached to a GameObject. Note that we can also edit Object variables in the GameObject Inspector. Scene variables are shared across all the script graphs in the current scene. We can also edit these scope variables in the Inspector of the ‘Scene Variables’ GameObject placed in the scene. This GameObject will be created by Unity. Application variables are accessible from any script graph; their values remain even when the scene changes. However, they will reset once we quit the game. Saved variables will persist even after we quit and resume the game. Why should we use a small scope when one could use a larger access scope, like the Application scope? There may be times when different objects will have similar variables, for example, health points. All enemies will have health points, but we need to differentiate each enemy’s health separately, according to the damaged they have taken. It can be confusing at first. But over time, it will become evident which scope to use. To add a variable, we choose the relevant scope tab, name the variable, and press enter. We can now select the data type the variable will remember, then we will fill in an initial value. Under the Saved scope tab, we have Initial and Saved sub-tabs. In the initial tab, we define the values that will automatically be created for new games. In the saved tab, we can see the state of saved variables for our current computer. In the graph, we use the Get Variable node to get the information stored in it. This node gives us the current value stored in the variable. Searching it at the Fuzzy Finder will present us with different scopes to select from. We can also change the scope at the nodes themself. We get our variable by either typing its name or selecting it from the list. In this example, I have connected the Get Variable node to a Debug Log node, which will print the variable’s value to the console. We can also change a variable’s value at any time by using the Set Variable node. In this example, I have created a Scene variable that remembers a boolean data type and set it to false. Collections are groups of items. Unity’s Visual Scripting provides us two collection types List and Dictionary. A list is a collection of objects sharing the same data type. The items stored in the list are sequentially ordered, meaning that the order in which items are added is maintained. In the Blackboard inspector, create a new variable; at the type field, write down ‘list’ and select which data type the list should store. We can now add as many Values as we like to be part of the list. We can also create a list by code using the Create List node. A few nodes are available for adding items to the list. With the List Add Item node, we connect the list and the item we want to add. The item will be appended to the end of the list. If we want to add an item to a specific position in the list, This node has a third input – Index, which is the intended position. Note that Index starts counting from 0. Therefore the first item’s index will be 0, the second is 1, and so on... We can also replace an item at a given index position with another using the Set Item node. With the Remove At node, we can delete an item from the list using its position in the index. We use the Remove node to delete a provided item with its value instead of its index. The Get Item node, as its name suggests, retrieves the item stored at a given index. We can fetch the first and last items using the First Item and Last Item nodes. We can ask whether or not an item exists in a list using the Contains Item node, providing it with a value. When we need to know how many items a list contains, we use the Count Items node. Finally, the Clear node will remove all items from a list at once. Another collection is the Dictionary, which allows us to map one value to another. When we create a dictionary, we need to specify which data type for an item’s Key and another data type for its Value. When adding an item to the dictionary, we specify what key will map to it. For example we may create a dictionary with a String for both the Key and the Value. Then, each item will have a person’s name as the key and the person’s home address for the value. We can then ask the dictionary whats the address for a given name is. To managing dictionaries, we use nodes similar to those introduced for managing lists. Loops allow us to repeat a section of our script multiple times. Note that all iterations happen right away and will only stop when the condition is reached. The While Loop node has a boolean Condition input and two Flow outputs: Body and Exit. The node will execute the Body flow repeatedly until the condition turns from true to false. At this point, the node will run the Exit flow. When can we use a While Loop? We may want an enemy to continue to chase the player as long as it’s seeing it. However, once the player is out of view, the chasing loop is halted. With the For Loop node, we can define how many repetitions the loop should go through. This node uses an Index to count the loop’s current iteration. The First number is the index’s initial value, and the Last number is the index’s upper limit; we will only get up to the last number and quite the loop just before we reach it. The Step will define the amount to increment the index after each iteration. An example of using a For Loop is spawning a specific number of enemies, configuring each one with a different weapon based on the Index value. The For Each Loop node iterates over a collection’s items. We pass in a list or a dictionary. The Item output provides us with the loop’s current iteration item. We may use this node to go through a list of the game’s characters and move each one of them. We can also connect Dictionaries to this node by toggling on the Dictionary option. With the Break Loop node, we can exit a loop at any given time. Furthermore, we can use it for any loop by using it inside the Body flow. The last part of this video is about working with Unity’s Game Objects. A Game Object is any object that appears in our game’s scene –  whether it’s a character, tree, camera, or light, if it’s in the scene, it’s represented by a Game Object. Every Game Object contains Components that define its properties and behavior. Adding components and tweaking their configuration differentiates between a character, a light, or a camera object. Since every Game Object is in the game’s scene, it has at least a Transform component controlling its location in the world. When we want to refer to a Game Object, we can use the This node, which will provide us the Game Object that the script is attached to. We can also use the Game Object Literal node to select a Game Object from the scene or a Prefab asset. An inactive Game Object exists in the scene but isn’t visible, nor does it or its components update. We may want to prepare a few enemies at our level and activate them progressively. To activate and deactivate a Game Object, we can use the Set Active node, passing it an activity boolean. This is like manually unchecking the check box in the Inspector. We have two nodes to ask whether a Game Object is active or not; Get Active Self will tell us if the Game Object itself is marked as active, as in whether its Inspector’s checkbox is ticked on or off. The Get Active In Hierarchy node will check whether the Game Object is active and whether all of its parents are active. Usually, we use the Hierarchy version as it’s more practical. When making new Game Objects, we have two paths to choose from: duplicating an existing object or defining a new one. To duplicate an existing Game Object, we can use the Instantiate node and pass it a scene Game Object or a Prefab asset Perfect for creating enemies in real-time, shooting bullets, etc. We use the Create Game Object node to create an empty Game Object while we play. We can also use the node variant with a Name input to control the game object’s name. The created Game Object is then available to us through the Result output we can use it to set the position or add new components using the Add Component node. Speaking of components, we can access a Game Object’s Component with the Get Component passing the desired component type. We can also go the other way around; if we have access to a component such as a Collider, we can use the Get Game Object node to retrieve the Game Object the Component is attached to. Remove a Component from a Game Object is achieves using the Component: Destroy node. We can use the Destroy node to remove a Game Object from the scene in real-time, along with all its components and scripts. It’s helpful if we defeat an enemy and now want to remove it from the world. In addition, we have a variant of Destroy with time which gives us the option to delay destroying the object. We can assign tags to Game Objects to categorize them. For example, we may use a “Collectable” tag to define all items in the scene the player can collect. Tags aid us in identifying Game Objects to treat them differently in our scripts. In the Game Object’s Inspector, we assign a tag in the dropdown near the name. We can either choose from Unity’s predefined tags or create a new one by choosing Add Tag... and, well, add a new tag. We can use the Get Tag node to retrieve the Game Object’s tag. We can assign a different tag to a Game Object with the Set Tag node. With the Compare Tag node, we can confirm if a Game Object’s tag matches another; we can use the resulting boolean to run a script only on specified objects. To look up Game Objects with a specified tag in the scene, we got the Find Game Object With Tag node. With this node, we can search for a Game Object at the scene by its tag; there are two variants for the node, one that returns the first matching object and another that returns all objects with the assigned tag. We can also use the Find node to get a Game Object by its name. Thank you for following along! Unity’s Visual Scripting provides us with tons of handy nodes to use, and while we did not cover all of them, you now got everything you need to know to start creating your own games. We will explore more nodes in the following videos, interacting with Unity’s different systems, such as Physics, Input, and more... So be sure to subscribe and let us know in the comments if there is anything, in particular, you are looking to learn about.
Info
Channel: NotSlot
Views: 11,213
Rating: undefined out of 5
Keywords: unity 2021 visual scripting tutorial, unity beginner scripting, unity beginner scripting tutorial, unity beginner tutorial, unity bolt, unity bolt nodes, unity bolt tutorial, unity tutorial, unity visual scripting, unity visual scripting 2021, unity visual scripting documentation, unity visual scripting graph, unity visual scripting tutorial, unity visual scripting vs coding, visual scripting in unity, visual scripting in unity tutorial
Id: JYkFm1Sc3v8
Channel Id: undefined
Length: 31min 9sec (1869 seconds)
Published: Wed Jun 23 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.