Below are som notes from a really good video on blueprint communication by Zak Parrish
Blueprint Communications | Live Training | Unreal Engine

Intro

  • A way for separate individual obejcts to talk to each other
  • Useful for:
    • Broadcasting an event to a number of listeners
    • Telling a specfic object to do something
    • Quering another object
  • UE4 has no way to just “send a broad signal to everyone”
    • Trivia: had it in UE2, but it wasn’t very efficient
  • Communication will always involve the following:
    • A Sending Blueprint
    • At least one Receiving Blueprint
  • Communication will always require a reference at some point
    • The Sender or Receiver has to become aware of the other
  • All Blueprint communication is 1-way
    • Blueprints can send data back and forth, but it requires both Blueprints to set up their own individual paths of communication
    • Queries are possible, but are initiated by the Sender (still 1-way)

Types of communication

  • 3 primary Blueprint communication Methods
    • Direct Communication
    • Blueprint Interface message calls
    • Event Dispatchers

When to use

  • Flow of communication
    • Is the sender pushing the data to the reciever? then use:
      • Direct communication
      • Blueprint interface communication
    • Are the receivers actively listening for the sender to do something? then use:
      • Event dispatchers
  • Which party can get a reference to the other
    • Can the Sender get a reference to the Receiver(s)? then use:
      • Direct communication
      • Blueprint Interface Communication
    • Can only the Receivers get a reference to the Sender? then use:
      • Event Dispatchers

Direct Blueprint Communication

Concept

  • One Blueprint is talking to another
    • Sender gains access to Receiver
    • Sender can then
      • query data and variables
      • Send data and update variables
      • Call functionality on the Receiver
  • Always 1-to-1 communication, not 1-to-many
    • You can use flow control techniques such as Loops to talk to many things
    • Each iteration of the loop is still 1-to-1!

How it works

  • Sender gets a reference to the Receiver
    • Many, many ways to do this. Examples would be:
      • Assigned at the start of game (BeginPlay)
      • Overlaps
      • Get All Objects/Actors of Class (very slow, use with caution)
  • Sender may need to Cast this reference to the thing it wants to talk to
    • This is is just a test to verify what it is you are talking to
    • If the Cast is successful, then the connection is complete
      • Sender can send data to or pull data from the receiver
      • Sender can call functions directly on the receiver
    • If a cast fails you can always cast to something else
    • If you already have a reference of the proper type, you don’t need to Cast!
    • Casting to a parent class you can not use functionality of child classes
    • Casting to low lowers flexibility and eliminates teh possibility of accessing sibling classes without further testing

When to use

  • You already know the following:
    • The Sending object
    • The Receiving object(s) - or you at least have a clear way to get a reference to them
    • What functionality or data you’re going to tap into
    • Basically, you know everything that could ever happen between these two things, you just need to make something happen.
  • If you don’t know everything:
    • You will likely wind up making a lot of Branch (If) nodes
      • If it’s a Box, open it
      • If it’s a Light, toggle it
    • This is generally not good. You should probably be using a different form of communication.

Demo

In this example we will extend the 3rd Person template and add some interaction to it. Launch a project using the 3rd Perseon template.

  • Add a Health variable to our 3rd person Blueprint.
    • Open up the ThirdPersonCharacter BP (Content > ThirdPersonBP > Blueprints) and double click it to open it up
    • Switch to the “Event Graph” tab.
    • In the Variable section of the My Bluepeint pane, click the plus icon to add a varaible.
      • Call it “Health”
      • Set the type to Float
      • Click compile
      • Set the deafult value to 100
  • Setup health drain
    Here we setup a health drain system using the built in node pain causing volume
    • Drag out a pain causing volume to the 3d view.
      • set the damage per second to 10
    • Since the volume does not render, we drag out a cube, position it on the ground and scales it so that if fits the volume.
    • Add a text render (optinally, only for viz purposes)
      • Set the text to “Hurt”
      • Position it the way you like, set color
    • Enter the ThirdPersonCharacter BP and switch to the Event Graph
    • Add an AnyDamage Event, start typing “any da…” select the Event AnyDamage
    • From the variables section drag out the Health variable we created earlier, select GET
    • From the output pin of the Health variable (we just added) drag out and release and type “-” select float - float
    • connect the “Damage” output pin to the to the second input of the subtract node.
    • Drag out the Health variable and this time select “Set Health”
    • connect the output pin from the subtract node to the input of the Health Set node
    • Also connect the output execute pin from the AnyDamage event to the Health node.
    • Click Compile
    • Note
      • We could add a print function to verify that our health draning is working.
  • Direct blueprint communication
    • Create a “Healing Volume”
      • RMB click in the content browser (in a place where you want to store your bp) > Blueprint Class
        • Based on Actor
        • Call it “HealingVolume”
      • Double click the blueprint to open it up
      • Add a Box Collision Component, call it Volume
        • Set teh extent to (100, 100, 100)
      • click the Event Graph tab to open it up
      • From the ActorBeginOverlap, drag out the “Other Actor” otput pin and release, strt typing “th” and select “Cast to Third Person Character”
      • Set the Health
        • Note
          • We could set the “Health” variable directly on the Third Person Character instance (taht we got a reference ty by casting) but that is not a good idea.
            • This would mean that the “Healing volume” has functionality that edits a variable of another instance
            • If there was a bug it could be hard to find where thsi was called from
            • Also might not be obvious to other peolpe opening you blueprint later on
          • Instead we will create a function inside the Third Person Character that sets the health, and we will call this function from the healing volume.
        • Add Heal All function
          • Go inside the Third Person Character blueprint
          • In the My Blueprint pane under the Functions section click the plus icon to add a function and call it “HealAll”
          • Inside the Heal All function drag out a setter of the Health variable
          • Connect the execute pin from the function to the setter
          • set the Health value of the setter to 100
          • optionally, we could add debug print node to informed that we have been healed
          • Comiple and save
        • Call the Heal All function
          • Open up the healing volume blueprint
          • From the “As Third Person Character” output pin drag and release and start typing “heal a…” select “Heal All”.
      • For visualization during gameplay we can select the textRenderActor and the cube we used for the health drain and place the according to the healing volume.

Blueprint Interfaces

Concept

  • A way to specify functionality without any kind of implementation
  • Any Blueprint that implements the interface is guaranteed to have those functions
  • The functions of the Interface can be given functionality in each of the Blueprints that implements it
  • Interfaces are 1-to-one communication
  • The sender needs some reference to the receiver
  • Interfaces dont care whether or not trhe receiving object knows about them.

How it works

  • Interfaces are a unique form of communication, they are their own asset
  • Blueprint Interfaces allow different Blueprints to share with and send data to one another
  • The use of Blueprint Interfaces allows for a common method of interacting with multiple disparate types of Objects that all share some specific functionality
  • In other words
    • You send data, called Interface Messages through that asset to listening objects
    • By default, nothing recieves interface messages
    • You have to implement the blueprint inteface onto the blueprints that will be recieving
    • This means that anything that doesnt need to respond to an interface simply doesnt have to implement the interface.
    • Only recievers need to implement the interface
    • Anything can send interface messages, whether it implements the interrface or not
    • it is perfectly safe to send interface messages to objects that dows not implement the interface, nothig will happen.

When to use

  • When you are sending a signal to some object and you dont really care what it does once it receives the signal
    • In fact, you dont even care if the receiver knows about the signal
    • You just want to send a signal to an object, if the know what to do whith it, great!
  • Example
    • Button B send out an InteractWithThings signal
      • Receiving object ‘X’ knows what to do with the signal because it implements the interface, and performs some action
      • Receiving object ‘Y’ also implements the interface but performs some other action.

How to

  • Create an interface
    • Blueprint Interfaces are created in the content browser
      • RMB click > Blueprints > Blueprint Interface
    • They have some limitations
      • Add new variables
      • Edit graphs
      • Add Components
    • In the blueprint interface editor:
      • You automatically get you first function
      • You can setup inputs/outputs
      • You cant setup any functionality, the graph is grayed out
  • Implementing an interface
    • In the receiving class, go under class settings
    • under implemented interfaces, add your new interface
    • recompile
    • you can now create an event in your graph named the same thing as your function
    • now when this class (instance I guess) receives the message for that interface function, something happens
  • Note
    • If the interface has a return value (output) it gets implemented as a Function on the receiving object.
    • If the interface has no return value (output) it gets implemented as an Event on the receiving object.
      • It can still have inputs

Extra

  • Interfaces can be used for communication bewteen sub-levels
  • Self calling
    • Once an interface function has been implemented on the receiver, the receiver can then call that functionality on itself.
    • this is useful to guarentee that a given object has a certain set of functionality
      Think of this like a shortcut so you dont have to repeatedly setup the same functions on objects that inherit from different hierarchy branches

Demo

Sender

In this example we will extend the 3rd Perseon template and add some interaction to it. Launch a project using the 3rd Perseon template.

  • Setup inputs
    • Project settings > Engine > Input > Bindings
    • Lets add one action
      • Under action mappings click the plus to add a new action mapping
        • Give it the name “InteractButton”
        • Set the key value (to trigger the action) to the “E” key
          To more easily find the key, type “e” followed by a space to find the key in the dropdownlist
  • Create an interface
    • In the content editor (in the directory you want to save your blueprints) RMB click > Blueprints > Blueprint Interface
    • call it “iInteractable”
      the name used for the interface can start with lowercase “i” followed by an adjective. For instance “iInteractable”, “iClonable”, …
    • Double click the interface to open it up
    • Add functions
      • Give the first (already existing) function the name “Interact”
      • Create a new function (by clicking the plus in the top right corner of the “My blueprint” tab) and call it “GetInteractState”
        Note that when you add a new function a new tab on top of the network pane is added
      • With the “GetInteractState” selected in the “My blueprint” pane, click the plus on the right side of the outputs in the details pane. The type should be boolean and the name we can set to “InteractState”
      • Compile Click compile in the top left corner of the editor For the interface to be available in the editor we must compile it
      • We can close the blueprint editor
  • Setup the sender
    Here we will extend the ThirdPersonCharacter blueprint to make it possible to call the functions we specified in our interface using the input we setup earlier.
    • Open the ThirdPersonCharacter BP
      • Find the ThirdPersonCharacter BP (Content > ThirdPersonBP > Blueprints) and double click it to open it up
      • Select the Event Graph tab (if not open we can double click the EventGraphg in the Graphs section of the “MyBlueprint” tab)
      • Lets add the input action we setup earlier. Hit tab and start typing “interac…” select the action event “InteractButton”. This input action will trigger every time we press and relaes the E key as we set it up earlier.
    • Find object to interact with
      The idea is to do a trace in the scene to see if we can find some object to interact with.
      • Setup input for the SphereTraceByChannel
        • Press tab and start typing “trace…” select “SphereTraceByChannel”
          This node will sweep a sphere along the given line and returns the first blocking hit encountered. This trace finds the objects that RESPONDS to the given TraceChannel. Target is Kismet System Library
        • Now we will need a place to start the trace from, we will use the capsule componenrt of the 3rd person. From the Components pane (top left side, if not showing go to window > Graph editor and make it visible) darg and drop the Capsule Component to the blueprint graph
        • From the capsule component node (we just added to the graph), LMB press and drag out the blue pin into the graph and let go, in the popup dialog start typing “get world…” and choose “GetWorldLocation”
        • Connect the yellow output from the GetWorldLocation node to the “Start” input of the SphereTraceByChannel node. (this will be our trace start point)
        • now we need to calculate the end position. Drag the blue output of the capsule component, release and start typing “getf…” select “Get Forward Vector”.
        • To control the length of the line we will trace lets multiply the forward vector, drag out the yellow output from the get forwadr vector node, type “*” select “Vector * Float” and enter the value 100 in the multiply node.
          • Note that in UE5 Early access the second input type of the multiply node is based on the input type, but if we want a float we can RMB the second input pin > Convert Pin > Float
        • We will the promote the value of the multiply node to a variable, RMB click the green value pin > Promote to Varaible. This will select the variable in the my blueprint pane, so we can just start typing “TraceLength” to give it that name.
          The value we entered, will be set as the default value of the variable.
        • Then we add the capsule world location and the multiplied forward vector to get the end position, from the “GetWorldLocation” node yellow output pin drag out and from the piopup list type “+” and select “Vector + Vector”
        • connect the output pin from the multiply node to the second input of the add node and connect to the “End” input of the “SphereTraceByChannel” node.
        • on the “SphereTraceByChannel” node set the radius value to 50, RMB click the value and promote to parameter, name it “Trace Radius”
        • We also need to connect the “Pressed” execute pin from the “InputAction InteractButton” (that we added earlier) to the input execute pin of the SphereTraceByChannel node.(this will run the trace when the action is triggered)
      • Handle the trace hit objects
        • the output “Out Hit” of the SphereTraceByChannel node is a struct. We can split the struct to access “components”, RMB click the Out Hit > Split Struct Pin.
        • The “Out Hit Hit Actor” is the actor that we hit (if we hit any, that is)
        • To validate that the object we hit is valid we will use an isValid node. Click the out hit hit actor. drag out in the graph and release, start typing “isv…” select the “? Is Valid” (note that it have a prefixed question mark)
        • we also need to connect the output execute pin from the SphereTraceByChannel node to the input execute pin of the isValid node.
        • now we can verify if we hit a valid actor and send our “Interact” message that we created in the interface we setup earlier. press tab and start typing “Interac…” select “Interact (message)” (you can se that it belongs to I Interactable or iInteractable as we called it)
        • Connct the out “hit hit actor” from the “SphereTraceByChannel” and connect it to the “Target” input of the “Interact” node (the interface we created)
        • then we will connect the “Is Valid” execute pin form the isValid node to the input execute pin of the “Interact” node
      • Debug the traceing
        • Now we have a way to look for objects to interact with. To test and debug this functionality we can set the “Draw Debug Type” of the SphereTraceByChannel node to “For duration” this will show the trace in the viewport.
        • Compile rememnber to compile the blueprint, hit save and close the bp.
        • Now we can play the map and see our trace in action.

Lets collapse the trace setup into a macro so that we can reuse it elsewhere in the graph. Note this is optional, it will not change the functionality, but make it easier to re use the functionality.

  • Collapse to Macro (optional)
    • Select all nodes we created before except the “InputAction (Interact button)” and the “Interact” (Message) function of the iInteractable interface and RMB click and select “Collapse to Macro”. Give the macro the name “TraceForInteaction”
      • A macro is a way to collapse nodes into one node that can be reused elsewhere (inside the same blueprint). If you want to node setup to be used in another blueprint, you should “collapse to function” instead. The “Collapse Nodes” simply groups the node inside a parent node. If you duplicate a macro or a function, you will get instances of the same where if you duplicate colapsed nodes you will get duplicates.
    • Clean up the output pins. Double click to enter the macro, select the “Outputs” node, and in the details pane expand the outputs section and click the arrow on the right side of the “Out Hit Hit Actor” to move it to the button (we could of course also move isValid up) and hit compile.
      This step is not necessary but can visually look nicer

Reciever

Lets build a door that we can interact with.

  • Create the Door blueprint
    • Navigate to a dir in the content browser where you want to save your door blueprint.
    • RMB Click > Blueprints > Blueprint Class
      • Pick parent class > Actor
        And call it “InteractiveDoor”
    • Add the interface
      • Double click the blueprint to open it up
      • In the top bar select class settings, in the details panel under the section Interfaces click the add button and select the “iInteractable” interface form the list.
        • Tip: you can type “ii” to quickly find the iIntaractable in the list
        • Note: when the interface is added, it will be visible in the My Blueprint tab under the Interfaces section. It will also list the functions and events that we created in the interface. Important you must press compile for the interface functiosn to be visible in the event graph… so press compile.
      • Lets promote the interact state (that we get from the GetInteractState function in inteface) to a variable that we can use in our event graph.
        • Double click the “Get Interact State” in the interfaces section of the My Blueprints tab. This will open it in the graph.
        • RMB click the “Interact State” on the return node > Promote to Variable
          • This will make it possible to use this variable elsewhere in this blueprint.
          • Also note that it appears in the Variable section in the my blueprints tab
        • Click Compile
    • Add door components
      • Display and Collision
        • Lets add a component that will be the visual represenatation of the door
          • In the components pane click Add Component > Cube.
          • Rename it to “Door”
          • Lets scale the door so that it looks like a door
        • Then we will add a Box Collision component that we will interact with
          • In the components pane click Add Component and type “box…” in the search filed and click “Box Collision”
          • Note that this needs to be a direct parent of the DefaultSceneRoot. If it is a child of the Cube it will move wioth the cube if that is aninated and is not what we want.
          • This is importatnt if lets say the doors open upwards or opens in a way that we can not reach when the door is in the opened state. (The SphereTraceByChannel will trace in the forward direction so we might have no way to reach the door)
          • Next we will edit the collision behaviour of the box collision component to match what we have setup in the SphereTraceByChannel node.
            • With the box collision node selected, in the details panel under the collision section we will set the Collision Preset to custom. (this will expand the menu)
            • Click the Ignore checkbox to ignore all events
            • Then we will enable the Block checkbox on the visibility (channel of the custom collision)
              • If we go inside our “Trace for Interacation” macro we made earlier we will se that the “Trace Channel” of the TraceBySphereChannel is set to visibility.
              • Todo: look into difference btw overlap and block…
      • Setup animation
        There are many ways to setup animation this is one way…
        • Add start location
          • In the My Blueprint pane in the Variables section click the plus to add a new variable
          • Make it a vector and call it StartLocation. This can be done directly in the variables section in the My Blueprint pane or with the variable selected we can edit the properties in the details pane.
            • Note that on the right hand side you can choose if the vector should be an single value, array, set or map(dict) we want it to be a single value.
          • Click Compile
          • Select the “Door” (the cube component that we use to display our door) and in the details pane under the Transform section RMB click Location > Copy
          • Select the StartLocation variable and in the details pane under default value RMB click Start Location and Paste the copied location.
        • Add end location
          • In the My Blueprint pane in the Variables section click the plus to add a new variable
          • Set it to a (single value) vector and call it EndLocation
          • Set the default value to (0,0,300)
          • We want the end location to be editable with a 3d widget:
            • In the details pane under the varaible section, enable the “Instance Editable” checkbox
              • Note that we also can make it public and editable by turning on the eye icon in the My Bluprints pane on the right side of the varaible in the variables section.
            • Also enable the “Show 3D Widget” in the details pane under the varaible section
        • Add Timeline
          • Step into the event graph of the interactive door blueprint
          • Add a “timeline” node
            • Press tab, start typing “timel…” select “add Timeline” and call it “DoorTimeline”
            • Double click to enter the timeline node
            • Click the “Add Float Track” (the left f icon top left)
              • Call the track “DoorInterpolation”
            • Shift click 2 times in the time line to add keyframes. It is not really importatnt where we click we can edit this later.
            • select the first keyframe, set both time and value to 0
            • select the second keyframem and set the time to 0.75 and the value to 1
            • select both keyframes and press 6 to flatten the curve handles or RMB > Flatten
              • In UE5 it seems like we first need to press 1 (auto) then 6 (flatten)
            • Note be sure to enable the “Use Last Keyframe” if this is not enabled you can get some weird results with the animation, probably caused caused by the timeline keeps on playeing until the end of the timeline.
              • I guess you also could manually set the length of the time line to the time of the last keyframe. Maybe use last keyframe is a shortcut for that?
        • Setup the lerp
          • click on the “Door Interpolation” output pin on the timeline node, drag out and release in the graph, start typing “lerp…” and select “Lerp (Vector)”
          • From the “Variables setion” of the My Bluprint pane drag and drop the StartLocation to the A input pin of the lerp node
          • And drop the EndLocation to the B input pin of the lerp node
          • Drag out the Door component (from the components pane) and drop it on the event graph
          • From the door component (that was dropped in the graph) drag out from the output pin and release in the graph, start type “set rel…” select “Set Relative Location”
          • Connect the output from the lerp node to the “New Location” input of the Set Relative Location node
          • Connect the execute pin from the timeline node to the input execute pin of the Set Relative Location node
        • Drive timeline with Event
          • Add the interact event. In the event graph press tab and start typing “inter…” select “Event Interact”
            • This is the event that gets called when the E key is pressed
          • Next lets add the Interact State varaible to the graph so that we can check the state. from the Varaibles section of the My Blueprint pane drag and drop the “Interact State” variable to the event graph > Choose the “Get Interact state”.
          • Add a Branch node by holding B and LMB clicking the graph (or use the tab menu)
          • Connect the out execute pin from the Interact event to the input execute pin of the branch node
          • Connect the output from the (Get) Interact State to the Condition input of the Branch node.
          • Based on the state of the interact variable we want to do 2 things:
            • If the Interact state is true it means that the door has been opened so we want to set the state to false and close the door
              • So lets get a setter of the interact state by draging and dropping the Interact State variable to the graph and > choose the “Set Interact state”
              • Then connect the “True” execute pin from the branch and connect to the setter of the Interact state.
              • Connect the output of the setter to the “Reverse” input execute pin of the Timeline node.
            • And if the state is false, we want to set the state to true and open the door
              • drag and drop a new Interact State setter (or copy/paste)
              • Then connect the “False” execute pin from the branch and connect to the setter of the Interact state (that we created in the step before).
              • Note: We now want to set the Interact State to true, so we need to enable the checkbox of the setter.
              • Connect the output of the setter to the “Play” input execute pin of the Timeline node.
        • We should now have a working interacatble door!
          • We could set the Draw Debug Type of the TraceSphereByChannel node to None

Event Dispatchers

Concept

  • A way to establish a listening-type relationship so that the Receiver is “listening” for an event on the Sender to take place. It can then respond however it likes.

How it works

  • In the Sender Class
    • Create a new Event Dispatcher in the My Blueprint panel
    • If you have to pass along any data (like current Health) that becomes an Input
    • At some point in your Event Graph your sender must Call this Event Dispatcher
      • Drag a reference to the Event Dispatcher into the Graph, choose Call.
  • In the Receiver Class
    • You must have a reference to the sender! It’s your responsibility to get that!
    • Once you’ve confirmed the Sender class is the one you want (you might need to Cast here)…
      • You Bind to the Event Dispatcher by name
      • Create a Custom Event from the Event Pin
      • That Custom Event will be fired whenever the Sender calls their Event Dispatcher
    • Know that you may need to stop listening at some point
      • This means unbinding the event.
      • This is very easy if you stored a reference to the Sender class before Binding.
    • If no objects have made a Bind to an Event Dispatcher:
      • When the Dispatcher is called, no one is listening and nothing happens. This is perfectly safe.

  • Event dispatchers on the sender
    • From the Sender’s perspective, you only need to setup the Event Dispatcher and then Call it at some point in the Event Graph
      • Generally in response to some important event happening on the Sender
      • Notice that the Call does not require a reference to any other object! Instead, the Sender calls the Dispatcher on itself!
  • Event Dispatchers on the Receiver
    • Any object wanting to become an Event Dispatch Receiver must:
      • Have or obtain a reference to the Sender object
      • Bind its own Custom Event to that Dispatcher
        • This Custom Event must have the same Signature as the Event Dispatcher
    • Once the Bind is complete, the next time the Dispatcher is called, the Receiver’s Custom Event will fire in response!
  • Event Dispatcher Signatures
    • Signatures are a specific combination of inputs on a Dispatcher
    • These can be shared if you are going to be creating a Dispatcher for an already existing event
    • Signatures can be used to make Dispatchers intelligent
      • Test the input data, do different things based on what you find
    • Unreal does most of the heavy lifting for managing signatures
      • But if you’re trying to Bind an already existing Custom Event, the signature must match!
  • Event Dispatcher Options
    When you drag an Event Dispatcher into an Event Graph or try to access one from a Receiving object, you see a lot of options. What do they all mean?
    • Call
      • This will broadcast the Event Dispatcher to any Receivers, if there are any
    • Bind
      • This will create a Bind node, used to bind a specific Custom Event so it fires in response to the Dispatcher
    • Unbind
      • Creates an Unbind node, used to unbind a specific Custom Event from an Event Dispatcher so you’re no longer “listening” for it
    • Unbind All
      • Creates an Unbind All node, which will unbind all events from this Dispatcher across all objects in the game. No more listeners!
    • Event
      • Adds a Custom Event with a Signature matching the Event Dispatcher
    • Assign
      • a Bind node with an attached Custom Event that has a Signature matching the Event Dispatcher

When to use

  • When you have a single event on a Sender that needs to be received by a lot of different Receivers, each doing their own thing
    • The Sender cannot receive a return value from Receivers
  • You start off knowing who the Sender is
    • But you don’t know or care who the Receivers are
    • You plan to setup n-number of Receivers later
  • The Receivers all get a reference (know about) the Sender
  • The Receivers also know when to start listening for specific events
    • Also potentially know when to stop listening!
    • Depending on your setup, it may be dangerous to leave a Bind in place forever
      • In these cases, you will need to Unbind

Demo

We will continue using the 3rd Person template we modified in the direct communication demo.

  • Create the UI widget
    • RMB click the content browser (in a dir where you saves your blueprints) > User Interface > Widget Blueprint call it “HealthUI”
    • From the Palette pane under the panel section drag and drop a “Horizontal Box” to the work area.
      • Position it and scale so that it looks good.
    • From the palette > common drag a “Text” widget and drop it insiude the horizontal box
      • Set the content > text to “Health: "
      • optinally edit some of the text settings to make it look nice
    • From the palette > common drag a “Progress Bar” and drop it on the right side of the text widget
      • with the progressbar selected in the details pane under the slot(Horizontal box slot) click the “Fill” button to fill the horizontal box
      • In the top of the details pane make sure “Is Variable” is enabled
      • give the progress bar the name “HealthBar”
    • click compile and save
  • Add the UI
    • Open up the ThirdPersonCharacter blueprint
    • In the event graph press tab and start typing “beg…” select “Event BeginPlay”
    • press tab start typing “create wi…” select “Create Widget”
      • On the right side of the class input pin select “HealthUI” from the dropdown
    • Connect the output execute pin of the “Begin Play” event of the “Create Widget” input execute pin
    • Assign “Owning Player” (not necessary in this case but good practice)
      • press tab and start typing “get con…” select “Get Controller”
      • The Owning Player expects a player controller so we need to cast to that
        • press the return value output pin (of the get controller) and drag out and release in the graph start typing “player…” select “Cast to Player Controller”
          • Since we are inside a third person character bp we know that the cast will work so we can RMB click the cast to player controller node and select > “Convert to pure cast” (at the bottom of th e menu)
            • This will remove the execution pins to make the node more versatile (note the cast could still fail. resulting in an invalid output)
            • This is only useful if you know for certain that the cast will be successful, which we know since we are inside a third persion blueprint that has a player controller
    • Create a variable for the ui
      • on the “Create (Health UI) Widget” RMB click the “return value” output pin and select “Promote to Variable” call it “HealthHUD”
    • Add to viewport
      • On the blue output pin of the set varaible node press and drag out to the graph, start typing “add to…” select “Add to Viewport”
        • sidenote the “Add to Player Screen” is for split screen games
  • Add Event Dispatcher
    • Performance
      • Do not use Bind (update on every tick) to update Health it is not performant
      • Instead use an Event drivent approach where you only update then the Health value has changed
      • Even in cases where you want to update quite often, lets say meter in a flight simulator and you want to update the altometer, you could use a timer to update maybe 10 times per second
    • In the ThirdPersonCharacter blueprint (that we set up in the direct communication demo) we printed the health to the screen, we will now instead update the HealthHUD, so lets remove the print nodes
    • In the My Blueprint pane under the Event Dispatchers click the plus button to add an event dispatcher and call it “UpdateUI”
    • With the event dispatcher selected, in the details pane under the inputs section click the plus icon
      • Call it “Health” and set the type to Float
        • Note that you have a drop down where you can copy signatures from other event dispatcher to save time
    • Drag the event dispatcher into the graph and select “Call” from the popup menu
    • Connect the execute & Health output pins from the “Set” node to the input pins of the event dispatcher.
    • Open the “Heal All” function, drag and drop the UpdateUI event disptacher, select “Call” and connect the pins as before
    • Compile and save
    • Now we have an event dispatcher we can listen to from our Healt ui and update the graphics
    • Lets also dispatch an event when the HealtUI gets added to the viewport (on BeginPlay)
      • Either drag out the UpdateUI event dispatcher as before or
      • drag out the output execute pin of the “Add to Viewport” node and start typing “call…” select “Call UpdateUI”
      • From the variables section of the My Blueprint tab drag out the Health variable and drop on the Health input pin of the “Call UpdateUI” event dispatcher.
        • Note that if we drop it on the pin we do not get promted if we wanr a get or set it understands that we want to get thae variable.
  • Bind to the event
    • Set the HealthBar progress
      • Doubleclick the HealthUI widget to open it up
      • In the top right corner click the Graph button to open up the Event Graph of the widget
      • Press tab start typing “get owni…” select “Get Owning Player Pawn”
      • Drag out the blue output pin of the get owning palyer pawn release and start typing “cas…” select “Cast to ThirdPersonCharacter”
      • Connect the “Event Construct” output execute pin to the input execute pin of “cast to third person character” node.
        • the “Event Construct” is called after the underlaying slate widget is constructed
      • Drag out from the output pin “As Third Person Character” on the “Cast to ThirdPersonCharacter” node release and strat typing “assi…” select “Assign UpdateUI”
        • This will add a custom event and hook up necessary things
      • Lets name the custom event “UpdateHealthBar” since that is what the custom event will do
      • Since we gave our progressbar the name “HealthBar” it will be listed in the variables section on the My Blueprint tab.
      • Drag out the “HealthBar” variable to the graph and choose “Get HealthBar”
      • from the blue output pin of the “HealthBar” variable drag out and release start typing “set” choose “Set Percent”
      • Since the progressbar goes from 0-1 and our Health is in range 0-100 we need to divide the Health with 100.
        • From the “Health” output pin of our “UpdateHealtBar” custom event drag out and release type “/” and select “float / float”
        • In the green input field enter 100
        • finally connect the output of the “float Divide” node to the input pin “In Percent” of the “Set Percent” node
        • Also connect the output execute pin of the “UpdateHealtBar” custom event to the input execute pin of the “Set Percent” node
        • press compile and save
      • we now have a working HealthBar!
    • Set color of the healthBar (optinal)
      Lets set the color of the health bar when it drops under a certain amout
      • From the “Health Bar” (the varaible in our graph that is a reference to the progress bar in our ui widget) from the blue output pin drag and release and start typing “col…” select “Set Fill Colour and Opacity”
        • on the node change the “In Color” to red
      • Now we mneed to check the amount of health, and if the value is below a certain value
        • From the node where we divide the “Health” variable by 100, click the green output pin press, drahg out and release and type “<” select “float < float”
        • on the “less than” node select the input value and set it to 0.5
          • this means that the boolean will be true if the health drops under 50 %
        • Add a branch node (Hold “B” and click in the graph)
        • Connect the output pin of the “Less than” node and connect to the “Condition” input pin of the branch node
        • Connect the output execute pin of the “Set Percent” node to the input execute pin of the Branch node
        • Connect the “True” output execute pin of the branch node to the input execute pin of the “Set Fill Colour and Opacity” node
        • Finally we want to set the health bar to green if we have more then 50 % health
          • Copy the “Set Fill Colour and Opacity” node
          • Set the color to green
          • Connect the “False” output execute pin opf the branch node to the input execute pin of the “Set Fill Colour and Opacity” node (that sets the green color)
          • connect the blue output pin from the “Health Bar” (the varaible in our graph that is a reference to the progress bar in our ui widget) to the “Target” of our “Set Fill Colour and Opacity” node (that sets the green color)
        • Compile and save
        • We should now have a working ui!

Conclusion

  • Lots of ways to get Blueprints to communicate
  • In many cases, more than one approach will apply
    • Just because there are other ways to do it doesn’t necessarily mean you’re wrong
    • Also doesn’t mean you’re right.
      • Consider all the angles discussed here and it should become clear which one to use
  • Teams need to work together to determine best approach
  • Unify and standardize
    • Agree on what types of approaches are to be used under what circumstances
    • If everyone is handling communication a bit differently, it’s hard to work together
    • Blueprint Coding Standards
      • Make them early
      • Use them immediately
      • Enforce them for all projects

Misc

  • Bluprint standard tabs
    • If you have closed the viewport, eventgraph and construction script you can open the:
      • Viewport by double clicking a component in the “Comnponents” pane
      • EventGraph by double clicking the EventGraph in the “Graphs” section of the in the My Blueprint tab
      • Construction Script by double clicking the Construction Script in the “Functions” section of the in the My Blueprint tab
  • Blueprint Parent Class
    • You can view the parent class of a blue print if you open the blueprint up, click on the Class Settings button on top toolbar and in the details pane under Class options you can see the parent class
  • Print String
    • There are some options on the Print string node if you expande the node. You can set duration, color etc.
  • Child class
    • To create a child class (based on an already existing blueprint, which will become the parent class) in the content browser RMB the blueprint > Create Child Blueprint Class