InjectedMeshConfig
. Once this input is created, we can incorporate a simple check in our blueprintâs execution flow to see whether the caller has provided a MeshConfig.
Now that our InjectedMeshConfig input is in place, we need to handle the scenario where it is not provided (i.e., itâs null
). To accomplish this, weâll introduce a Branch node that checks whether a valid MeshConfig has been passed into the blueprint.
First, spawn a Branch node in your graph, connecting it to the next step in your blueprintâs flow. The Branch node evaluates a boolean condition, then routes the execution to True or False pins based on the result.
PB_Body_Standard
mesh.BP_SpawnBody
. This blueprint will be responsible for spawning and configuring our bearâs body mesh and applying the stylized fur material that brings it to life.
SpawnMesh
node to make this happen. This node requires three key inputs: a mesh resource, a parent SceneNode, and a MeshConfig.
For the mesh resource, weâll directly reference the PB_Body_Standard.glb
file, as the bearâs body mesh will remain consistent across all use cases and doesnât require runtime variability.
Now, regarding the Parent (SceneNode
) and Config (MeshConfig
) inputsâwhile weâve already created these in our main Bear blueprint, they donât exist within this new BP_SpawnFur
blueprint. Since sub-blueprints do not have access to their parentâs internal variables, we need to explicitly define them as inputs to our BP_SpawnBody
blueprint so they can be passed down when executed.
To do this, navigate to the Blueprint Inputs panel of BP_SpawnFur
and create the following:
SceneNode
, named Bear-SceneNode
MeshConfig
, named Bear-MeshConfig
SpawnMesh
node.
ExecuteBlueprint2
node to run our newly created BP_SpawnBody
. Once added, select BP_SpawnBody
from the dropdown in the node, and youâll see the input fields update to match the ones we defined earlierâautomatically exposing the Bear-SceneNode
and Bear-MeshConfig
inputs.
Now wire up the execution flow so that both paths from the earlier Branch
node lead into this ExecuteBlueprint2
call. This ensures that regardless of whether we created a new MeshConfig or used an injected one, we always proceed to spawn the bearâs body.
Lastly, connect the two variables we previously createdâBearSceneNode
and MeshConfig
âinto the corresponding inputs on the ExecuteBlueprint2
node.
First
node, allows us to yield the first (and in our case, only) mesh renderer, which we can then feed into the Apply Material node.
Resource<Texture>
for the diffuse texture. Give your new input a name and a default textureâwe will use the name Fur-DiffuseTexture
and give it the default value T_PB_Fur_RaspberryRipple_1024.png
.T_PB_Body_Standard_LOD0_NR_1024
T_PB_Body_Standard_LOD0_ORM_1024
T_PB_Body_Standard_LOD0_H_1024
T_PB_Body_Standard_LOD0_CSTM_1024
BP_SpawnBody
blueprint, allowing it to be overridden by a parent blueprint or defaulting to the value we set earlier. However, our main Bear blueprintâthe one from which weâll eventually create instancesâdoesnât yet expose this input itself. To ensure we can control the fur texture (and thus the color) from our instances later on, letâs add a matching input to the Bear blueprint with the same default value. Once added, simply pass that input down into the BP_SpawnBody
execution, wiring it to the corresponding input to maintain consistency.
BP_SpawnEye
. This blueprint will handle all the logic for spawning and configuring a single eye. Then, within our BP_SpawnBody
blueprint, weâll simply call BP_SpawnEye
twiceâonce for each eyeâpassing in the appropriate mesh and texture for the left and right sides respectively.
Letâs go ahead and create that new blueprint now.
SpawnMesh
node to bring our eyes into the scene. As a quick refresher, this node requires three key inputs: a Mesh Resource, a Parent SceneNode, and a MeshConfig.
Unlike our previous body blueprint where the mesh resource was fixed, the eye blueprint will need all three values to be passed in from the outside. This ensures it remains flexible and reusableâallowing us to use the same blueprint for both the left and right eye, with different inputs for each.
Letâs go ahead and define the inputs in our blueprint now:
Resource<Mesh>
input with name Eye-MeshResource
SceneNode
input with name Bear-SceneNode
MeshConfig
input with name Bear-MeshConfig
SpawnMesh
node.
BP_SpawnBody
blueprint, we can now follow on from spawning the bearâs body and applying its fur by executing our newly created BP_SpawnEye
blueprintâtwice, once for each eye. Just like before, weâll use the ExecuteBlueprint2
node to call the eye blueprint and pass in the necessary inputs.
For both calls, weâll connect the existing Bear-SceneNode
and Bear-MeshConfig
variables to their respective inputs on the node. The only thing that changes between the two executions is the mesh resource we provide to the EyeResource
input.
SK_PB_Standard_EyeLeft_LOD0
SK_PB_Standard_EyeRight_LOD0
BP_SpawnEye
blueprint, letâs continue from where we left off after spawning the mesh by applying a materialâjust as we usually doâusing the Apply Material node.
As always, we can leave the Index input of the Apply Material node at 0
(targeting the first material slot). For the Renderer input, weâll use the first (and only) renderer returned from the SpawnMesh outputs. To retrieve it, we can use the First node from the array.
true
, then connect the texture output to the Diffuse Texture input of the Make PBR Material node.
Now for the actual texture resourceâwe want to make this customizable, so letâs create an input in our graph of type Resource<Texture>
and name it Eye-DiffuseTexture
. We can give this a default value for testing, feel free to use any of the included eye BC textures:
T_PB_Eyes_Green_BC_1024
T_PB_Eyes_Purple_BC_1024
T_PB_Eyes_Red_BC_1024
false
this time. Since these textures wonât change, we can directly reference them. The textures to use are included in your resources and map to:
T_PB_Eyes_NR_1024
T_PB_Eyes_ORM_16
UseDiffuse
1
1
0.5
0.5
true
true
Eye-DiffuseTexture
is an input to the BP_SpawnEye
blueprint, which means it can be set within the BP_SpawnBody
blueprint that calls it. However, to make customization even more accessible, we want to expose this input at the top level in our BP_Bear
blueprint.
To do this, weâll add a new input to the BP_SpawnBody
blueprint and link it to the existing input when executing BP_SpawnEye
.
BP_Bear
blueprintâadding a new input and connecting it to the ExecuteBlueprint2
node for BP_SpawnBody
.
In-BodySkeleton
, and setting its type to MeshRenderer.
After spawning the eye mesh and applying a material, insert a Branch node. Use the getter for your In-BodySkeleton
input and connect it to an IsNull node. The output of that node will control the condition of your branch, determining whether or not we proceed with binding.
Now, on the FALSE path (meaning the skeleton is valid), drop in a Bind Meshes node. This is what links the eyes to the bodyâs rig so they animate together naturally.
The Bind Meshes node expects two inputs:
BP_SpawnBody
blueprint. For now, the Spawn Eye blueprint setup is complete.
BP_Accessory
. This blueprint will resemble much of the logic from the main bear blueprint but focused on accessories instead of a full character.
In the Blueprint Inputs panel, add a new input of type SceneNode
, naming it something like In-Parent
. This input will determine where in the scene the accessory is attached; if a valid scene node is passed in, the accessory will become a child of that node. If not, it remains independent.
Inside the blueprint, place a CreateSceneNode node. Drag In-Parent
from your variables into the graph and connect it to the Parent pin of CreateSceneNode. This ensures that, if provided, the accessoryâs newly created scene node will be a child of the passed-in parent. For the Name, feel free to use something like âAccessoryâ.
Next, add a private variable of type SceneNode
âcall it Parent
to differentiate it from In-Parent
. Spawn a Set Parent node, linking it to the output of CreateSceneNode. This variable will be used later to anchor any meshes we spawn.
MeshConfig
âweâll call it In-MeshConfig
. This will allow the accessory to either use an existing config provided by a parent blueprint or create its own if nothing is passed.
Drag In-MeshConfig
into the graph and feed it into an IsNull node, then add a Branch node. Wire the boolean output of IsNull to the Condition input of the Branch, splitting the logic based on whether a valid MeshConfig has been provided.
With this branch node in place we can split the execution into two flows:
In-MeshConfig
is null, weâll create a new MeshConfig. First, add an input of type Resource<Mesh>
âcall it In-Mesh
âso that we can specify which mesh this accessory will use. Next, spawn a CreateMeshConfig node and connect In-Mesh
to its Resource pin.In-MeshConfig
is valid, weâll just reuse it.MeshConfig
âletâs call it MeshConfig
âand place Set MeshConfig nodes in each path of the Branch. In the true path, set it to the output of CreateMeshConfig, and in the false path, set it to In-MeshConfig
. This way, the rest of the blueprint can access a âfinalâ MeshConfig variable, regardless of whether we created it or inherited it.
In-Mesh
input.Parent
variable, which holds the scene node we created earlier.MeshConfig
variable, which now holds either the inherited or newly created configuration.In-Skeleton
of type MeshRenderer
. This will be the rig that the accessory meshes follow.
After spawning the accessory meshes, insert a Branch node to check whether a valid skeleton has been passed in. You can do this by using the getter for In-Skeleton
, hooking it up to an IsNull node, and feeding that result into the condition input of the branch.
On the FALSE path (meaning the skeleton is valid) drop in a Bind Meshes node to connect the accessory meshes to the skeleton. Just like before, this node needs two inputs:
Renderers
output from the SpawnMesh node into its Array
input. Youâll notice that the Array Element
type automatically updates to match the type of the input arrayâin this case, MeshRenderer
. This loop will give us access to each individual mesh renderer, one at a time.
The ForEach node provides two execution outputs:
Array Element
pin from the ForEach loopâthis ensures that each mesh renderer receives the material application.
UseDiffuse
, as weâll always want to use a diffuse texture for visual definition.
In-AlphaTexture
of type Resource<Texture>
.
Route this through a SetTextureSettings node to disable sRGB, and connect the output into the AlphaTex
input on the PBR material node.
Then, enable UseAlphaTex
by setting that checkbox to true
.
In-DiffuseTexture
of type Resource<Texture>
.DiffuseTex
input of the PBR material.BaseColor
input at its default.
UseAlpha
input should only be enabled if an alpha texture has actually been provided. To achieve this:
Get In-AlphaTexture
node.UseAlpha
input.0
.
1
for full visibility.
In-EmissionTexture
of type Resource<Texture>
.EmissiveTex
input.UseEmission
boolean input.EmissionColorBoost
and EmissionTintBoost
to 1
.UseEmissionTint
and EmissionTintColor
settings at their defaults.In-NormalTexture
and In-ORMTexture
of type Resource<Texture>
.UseNormalMap
and UseORM
, respectively.Occlusion
to 1
Roughness
to 0.5
Metallic
to 0.5
Apply Material
node you created earlier in the ForEach loop.
And with that, your base accessory blueprint is completeâflexible, modular, and fully customizable from the outside! All that is left is to start creating some accessories!
Accessories
folder in the Project Explorer, right-click and select New Blueprint Instance. Name this instance something descriptive; weâll go with BPI_Accessory_Head_Beanie
. Youâll be prompted to select a base blueprintâchoose the BP_Accessory
blueprint we just finished setting up.
Once your instance is created, head over to the Inspector panel on the left side and open the Overrides section. This is where youâll find all the configurable inputs that we exposed in the base accessory blueprint. Letâs go ahead and provide the correct values for our beanie accessory:
In-Mesh
: PB_Head_Beanie.glb
In-DiffuseTexture
: T_PB_Beanie_Head_BC_1024.png
In-NormalTexture
: T_PB_Beanie_Head_NR_1024.png
In-ORMTexture
: T_PB_Beanie_Head_ORM_64.png
BP_Accessory
. This time, however, weâll use the following overrides to configure our crown:
In-Mesh
: PB_Head_Crown.glb
In-DiffuseTexture
: T_PB_Crown_Head_BC_1024.png
In-NormalTexture
: T_PB_Crown_Head_NR_1024.png
In-ORMTexture
: T_PB_Crown_Head_ORM_1024.png
BP_Accessory
blueprint. Create a new blueprint instance and name it something like BPI_Accessory_Clothing_SpaceSuit
. When prompted, select BP_Accessory
as the base blueprint.
In the overrides section of the instance, plug in the following values:
In-Mesh
: PB_Clothing_SpaceSuit.glb
In-DiffuseTexture
: T_PB_SpaceSuit_Clothing_BC_1024.png
In-NormalTexture
: T_PB_SpaceSuit_Clothing_NR_1024.png
In-ORMTexture
: T_PB_SpaceSuit_Clothing_ORM_1024.png
BP_Accessory
blueprint as the foundation.
Create a new blueprint instance in the appropriate folder and name it something like BPI_Accessory_Clothing_HawaiianShirt
. When prompted, set its base to BP_Accessory
.
In the overrides section, set the following values:
In-Mesh
: PB_Clothing_HawaiianShirt.glb
In-DiffuseTexture
: T_PB_HawaiianShirt_Clothing_BC_1024.png
In-NormalTexture
: T_PB_HawaiianShirt_Clothing_NR_1024.png
In-ORMTexture
: T_PB_HawaiianShirt_Clothing_ORM_1024.png
BPI_Accessory_Eyes_CyclopsGlasses
, based on the BP_Accessory
blueprint.
In the overrides panel, set the following:
In-Mesh
: PB_Eyewear_CyclopsGlasses.glb
In-DiffuseTexture
: T_PB_CyclopsGlasses_Eyewear_BC_1024.png
In-NormalTexture
: T_PB_CyclopsGlasses_Eyewear_NR_1024.png
In-ORMTexture
: T_PB_CyclopsGlasses_Eyewear_ORM_1024.png
BPI_Accessory_Eyes_EyePatch
using BP_Accessory
as the base.
Apply the following input overrides:
In-Mesh
: PB_Eyewear_EyePatch.glb
In-DiffuseTexture
: T_PB_EyePatch_Eyewear_BC_1024.png
In-NormalTexture
: T_PB_EyePatch_Eyewear_NR_1024.png
In-ORMTexture
: T_PB_EyePatch_Eyewear_ORM_1024.png
BP_Bear
blueprint.
In-Skeleton
, which refers to the MeshRenderer of the bearâs body. This allows the meshes to animate correctly in sync with the bearâs movements.
Now hereâs the catch: the bearâs body mesh is actually spawned inside the BP_SpawnBody
blueprintânot directly within BP_Bear
. So we need a way to pass the MeshRenderer
back up to the parent blueprint so it can be forwarded to the accessory blueprints.
To do this, weâll use a Blueprint Output.
Head into the BP_SpawnBody
blueprint and open the Blueprint Outputs section in the inspector. Create a new output of type MeshRenderer
and call it Out-BodySkeleton
.
You may recall that right after spawning the body, we stored the first MeshRenderer
in a variable called BodySkeleton
. All we need to do now is expose that as an output. At the end of the graph, add a SetOutputs
node. This node allows you to specify what values to return to the parent blueprint. Connect the BodySkeleton
variable to the Out-BodySkeleton
input pin.
BP_SpawnBody
itself, you should also make sure to connect the BodySkeleton variable to the In-Skeleton input on both of your BP_SpawnEye
blueprint calls.
BP_Bear
blueprint, youâll now notice that the ExecuteBlueprint2
node calling BP_SpawnBody
now exposes an output pin for Out-BodySkeleton
. Letâs store this value in a new variable named BodySkeleton
of type MeshRenderer
. We can then use this variable to feed the In-Skeleton
input of our clothing accessory node.
ExecuteBlueprint2
node and tack it on to the end of our execution logic.
When working with the ExecuteBlueprint2
node, you can select a specific blueprint or blueprint instance directly from the dropdown. Once selected, UBF Studio automatically populates the nodeâs inputs and outputs to match the selected blueprintâs interface. You can try this now by selecting one of the accessory blueprint instances we created earlierâsuch as BPI_Accessory_Clothing_HawaiianShirt
âand youâll see all of the exposed inputs appear:
MeshConfig
, SceneNode
(Parent), and Skeleton
. The rest of the parametersâlike Mesh
, Textures
, and other visual elementsâshould be defined by the blueprint instance we pass in. Unfortunately, if we select a blueprint instance directly in the node, any unassigned fields are still overridden as null
âwhich unintentionally wipes out the default values inside the instance. In other words, weâre nullifying the behavior of the instance even if we leave those fields empty.
BP_AccessoryTemplate
.
In your Accessories
folder, create a new blueprint and name it BP_AccessoryTemplate
. Inside the Blueprint Inspector, add the following inputsâensuring the names and types match exactly with those from BP_Accessory
:
In-MeshConfig
â MeshConfig
In-Parent
â SceneNode
In-Skeleton
â MeshRenderer
BP_Bear
blueprint. In your ExecuteBlueprint2
node, select BP_AccessoryTemplate
from the dropdown. Youâll notice the node now exposes only the three inputs we care aboutâperfect for our needs.
Even though the node is configured with this template, we donât actually want to run that blueprint. At runtime, we want to dynamically execute the real blueprint instanceâlike the Hawaiian shirt. To support this, weâll create an input into BP_Bear
that allows us to specify which accessory blueprint (or blueprint instance) should be used.
Open the Blueprint Inputs section in the inspector panel and create a new input of type Resource<Blueprint>
. Name it In-ClothingBlueprint
. Then, simply drag in the new input into the blueprint and connect it to the Blueprint input pin on the ExecuteBlueprint2
node.
Finally, connect the three required input pins using the variables weâve already prepared:
MeshConfig
â In-MeshConfig
BearSceneNode
â In-Parent
BodySkeleton
â In-Skeleton
BPI_SimpleBear
blueprint instance and set the In-ClothingBlueprint
field to one of your accessory instancesâletâs go with the Hawaiian shirt for that perfect summer vibe.
Save your instance, open the UBF Previewer, and hit Preview in the top-right corner of the viewport.
You should now see your fully dressed bear, complete with laid-back island styleâready to party like itâs luau season in Fluf World!
[SpawnMesh] Failed to get input 'Config'
- this is an expected log and it occurs because the Previewer does not have any built-in configs.BP_Bear
blueprint:
In-HeadBlueprint
â Resource<Blueprint>
In-EyeBlueprint
â Resource<Blueprint>
ExecuteBlueprint2
nodesâone for each accessory typeâand connect them in series at the end of your existing execution flow. For each node:
BP_AccessoryTemplate
to expose the correct input signature.MeshConfig
BearSceneNode
BodySkeleton
Blueprint
input by plugging in the matching In-HeadBlueprint
or In-EyeBlueprint
input variable.BPI_SimpleBear
blueprint instance, and you should see both In-EyeBlueprint
and In-HeadBlueprint
as available fields. Select your favorite blueprint instances for each slotâweâll go with Cyclops Glasses and the Crownâhit Preview, and there you have itâŠ
A party-ready bear with full drip, from head to toe!