18. UE – How to generate dynamic icons from existing meshes

In this episode we’re going to take some skeletal meshes and create dynamic icons for them to use in Unreal Engine.

This will be used to extend our inventory base in this post and the result can be found in the next post here.

The details for this post can be found in this video

Create dynamic icons from skeletal meshes

The intention here is that I bought several assets for equipment, but they did not come with 2D assets – so I wanted to generate them dynamically.

I was thinking I could manually open each asset up and take some images for them, but that felt like it could take very long time, so I wanted to make something that would essentially dynamically generate the 2D assets for me run-time while I only provide the skeletal meshes for the items.

The inspiration for this came from the following video tutorial, and it will be a pre-requisite for the steps that I will cover below.

How do we generate the 2D assets?

From the YouTube tutorial above, you will come across 4 files that are created for this.

  • 3D Mesh capture blueprint
  • Mesh render target
  • Render target material
  • Widget with image displaying the material

Let’s discuss each file and what it’s purpose is and how we’ve modified it to get the results we desire.

3D Mesh capture blueprint

In this Actor blueprint class, we have

  • Spring arm
  • Scene capture component 2D (held by spring arm)
  • Skeletal mesh (as a variable – which you dynamically will change)
Example for the 3D Mesh Capture blueprint

Here you may want to play around with some ‘default’ settings. For example I wanted my items to always have a bit of a curve to them and predefined rotation so I updated them in the skeletal mesh settings.

You can set a skeletal mesh and play around with the settings to your liking.

Update the default transform for some skeletal meshes

Now let’s go into the construction script

Add blueprints for the construction script

This is doing quite a few things

  • Show only actor components – this is covered by another tutorial, we only show actor components in the scene capture, no background is included – this prevents overlap of items
  • set skeletal mesh (dynamically)
  • Reposition to make item appear more in center
  • update camera distance to handle zoom

Let’s talk a little more about step 3 and 4 as those are a bit more complex.

I inserted multiple items of varying length and height and their positions were a bit all over the place without those two steps.

I found that I needed to get the mesh to appear exactly center of camera, which was not happening by default – i.e. take a look at screenshots:

Axe showing as spawning in ‘center’ but skeletal mesh extends
The result is that top right of the axe is chopped off

However some other items appeared completely different, like so:

Staff item extended differently to the axe

The properties simply varied from mesh to mesh, so I tried to find programmatic way of adjusting it.

This is where Get Component Bounds came into play

Getting component bounds in ‘real space’

I will give quick sneak preview of me spawning this item into the world:

Spawning the 3D Mesh Capture BP – widget transform*

This is where the -100 came from – this has to be the same as whatever you’ve set this to.

I.e. The component bounds provided the delta from the center, which I used to adjust the position of the skeletal mesh. Maybe there’s a better way of doing it but this is one solution that I’ve found that seemed to work.

Next, I adjust the spring arm length, which determines how far the camera is from the skeletal mesh that you’re capturing.

Note that I’ve set the SceneCaptureComponent2D projection to a field of view of 30 degrees – which I believe means that for every 1 unit away, you can see around 2.5 units in height? I am not super confident in this but I think that’s roughly correct.

This is why from Skeletal mesh I get the box extent and obtain the Z axis (height of the mesh) and then I multiply it by 3 to set the spring arm length.

This gives me a nice field of view and the item has already been generally centralised.

Just note that after implementing the blueprints and compiling, you may not see the viewport as expected as the data is dependent on dynamic input (so testing can be more tricky). If you see something of the following, it’s expected:

The viewport may appear like this due to updates in constructor

Therefore you may want to disconnect the beginning parts of constructor (such as setting skeletal mesh dynamically) while working on the other pieces.

Mesh render target

There’s not much to say about this class – its basically one created in the tutorial video mentioned at start

The main thing to mention is that you have to link it to the Texture Target from the Scene capture component.

Linking the texture target

The result of it may look something like this:

Simple result from Mesh render target

Render target material

Again this is very similar to part from tutorial in video above but there is one small addition that you must make.

First of all this material should look something like this:

Material settings

You need to have the texture sample inserted from the texture sample in previous step.

What you will also need to do is convert the texture sample component to a parameter. This is because we will be creating material instances from this class. You can promote it to parameter by right clicking it and selecting Convert to parameter.

Convert to parameter in material

Name this parameter as ItemTexture or whatever you like.

Widget for the item

This is again from the tutorial but with some blueprint additions.

Generally you will have a Widget class with an Image component.

Widget with the image component for the 2D icon

Note that the image can be set straight to the material that we’ve generated.

This could be enough if you needed to only ever display one image at a time, but here we’re looking at spawning multiple icons dynamically, hence the new additions in the blueprints.

In this class we will look at spawning of the 3D Mesh Capture component dynamically.

Create a new custom event inside the Event graph and create a new custom event, I called it Update mesh.

When this function is called, we will spawn a new actor of the 3D mesh capture component class:

Inside the Event graph of widget, spawn the capture component

I get the player character and set the owner to the character – this is for future features of perhaps rotating the object etc. If you don’t need such features, you may leave the first block out.

Then I spawn the dynamic skeletal mesh that we’re interested in. Note the skeletal mesh is public variable. Therefore I can set it from step above which I will again show – but this is the input of creating our dynamic icon.

Next, I put together some ‘random’ transform for the position of this skeletal mesh. This doesn’t matter too much as we make the actor invisible to other cameras, other than the 2D capture component. But you should keep note of this transform as its used in the image inside 3D Mesh capture component – check for text widget transform on this page to find it. Note that transform of 0,0,0 did not work for some reason, not entirely sure why, so there may be some edge cases – its best for the point to not intersect with any other object where possible.

Next you do some interesting things.

Dynamically creating material instances for 2D Icon

Next, the 2D canvas that you had before we will dynamically create – so you’re technically not using it – but it was important for your testing so please don’t skip it! I’ve set the width/height to 1024, but it will depend on your requirements. Make this value smaller if you don’t need high def! As it will have performance impact if you spawn a bunch of them.

Next bit I personally found interesting.

We’re creating dynamic material instance object, which is really cool that UE allows this!

Note that the material you’ve created before is used here as the parent.

That’s why it was important to parameterize the texture property.

Here we are updating the Item texture parameter with the canvas target that we’ve dynamically allocated.

Then we simply update the image inside the widget with the material instance object and we’re basically done.

Using the dynamic 2D logo

Part of my inventory components, I have a entity for a inventory slot which has all properties for an item its storing, including the reference for skeletal mesh object.

Inventory slot example

The ItemRotatingWidget is the same widget that we looked at in the step above – I am also planning on making it rotatable in future!

For this moment, the setting of skeletal mesh was still disconnected for ‘testing/visualization’ purposes.

Setting skeletal mesh was disconnected to visualize the results

But in order to use the dynamic widget all you need to do is set the skeletal mesh to whatever mesh you like, then simply call the Update mesh custom event that we generated.

Set the skeletal mesh dynamically and update mesh

After this is done you can connect the setting of skeletal mesh dynamically and testing it for real.

Results

Here are just a couple items that I’ve dynamically set in my inventory and so far I think it’s looking great!

Dynamically generating 2D icons for my items of varying size

Here I am dynamically creating the 2D assets for each of my skeletal meshes. The cool thing is that the meshes are all of varying sizes but can still see them ok in the images.

Lighting

Feel free to add other things to your components, for example I thought the images looked dark so I can now add lighting to them. The beauty is that if I want to make a global change, ALL my icons are modified, making this scalable.

Add lighting source to your Item mesh capture

Disable the Cast shadows function as otherwise it can slow down performance. Tweak the light intensity as you like and check the results again!

Check the new 2D icons have dynamic lighting as we like

Now ALL the icons have the improved lighting effects. So play around with settings as you like to get the results you’re after.