22. How to create custom character creation screen with Unreal Engine part 3

This is the 3rd post for the following steps:

The objective of this post is to apply the settings from the right menu to the skeletal mesh on the left

Applying options to the skeletal mesh

I’ve integrated with several asset packs from N-Hance Studio (human male/female etc, I am not affiliated with them, but simply like their content.

Integrated with Modular Stylized characters

Note that you the steps that we cover will be relatively universal. I.e. we’re taking a generic approach to the problem, so solution should work for this asset pack and many others.

Ok let’s divide this post into few steps that we need to achieve:

  • Create the skeletal mesh on screen for us to use/modify
  • Create the data transfer objects (DTOs) between the widget and the skeletal mesh to apply styles
  • Create resolvers for the skeletal meshes and materials
  • Create the custom events to apply changes

Create the skeletal mesh for character create

So first of all, let’s find the base asset you want to use for your skeletal mesh.

I think one of the peasant ones is a good start for me from the assets I’ve purchased, here it is for reference:

Choose the asset you wish to use

Make a copy of this asset (in a folder of your choice) and call it something like BP_Create_Character – or anything else that makes sense to you.

It will look something like this by default:

Base stylized character

Essentially for most generic stylized character blueprints you will find that the options are essentially different components inside the components window. If you have this, its a good sign.

Now this blueprint has a parent class of Character as seen in top right. You will want to change this to skeletal mesh actor, by clicking File -> Reparent blueprint and selecting skeletal mesh actor.

You want to reparent because the character class will try move the mesh on input, consume controls and other similar behavior. For instance, it will block you from rotating the object if you wish to have that implemented.

Reparent option

Once done, confirm that this has worked.

Confirm the parent class is changed.

Next, all pieces in the event graph related to controls can be deleted.

Note that you may need to add a blueprint to Set Master Pose Component. This was in previous version of this blueprint but for some reason was removed in the updated version.

If you’re missing it, do add it.

Set Master Pose Component

This basically synchronizes the pose of all nested components to the root one. So set all nested components to target and set the root component as the master pose component.

Ok now you’re ready to spawn it inside the Create Character Blueprint.

Find the constructor in CreateCharacterWidget, and create a new function to spawn the character.

Spawn the skeletal mesh component in your widget

The full constructor for reference will look like this, and you will cover the rest of the functions soon.

Remember to call update character appearance at the end to refresh the expected appearance.

Inside the spawn character function we have:

Spawn character function

About getting the location for where to spawn, just drop something in the map and check the transform of it and use that as starting reference, then just play around with it until you’re happy.

Finding location where to spawn your character

You want to enable input incase you want to be able to rotate the character, which was covered here.

Understanding the stylized modular character mesh

Before we jump on building the resolver, let’s quickly summarize what we need to control in the character blueprint.

If you click on the skeletal mesh components inside the blueprint, you will load individual settings for them.

The key ones are:

  • anim class (not too relevant in this post, but will be important for you to recognize it in general)
  • skeletal mesh
  • material

So, the key is that each component has a mesh and appearance in separation. This implies that you will need to load them through 2 separate calls. It also means that items can share meshes and have alternating materials, giving you further flexibility in future if you require it.

Finding important settings in your skeletal meshes

Click on the magnifying glass on the skeletal mesh to find the blueprint and open it.

Inside here, you will find the relevant materials that the skeletal mesh requires. This is very important as different assets will have different names for the slots.

Finding slot names for materials

This is particularly important because some meshes will have more than 1 material – so perhaps you could use apply material by index (0), but as soon as you have >1 material assigned, your logic will break.

So make sure you find the relevant names and always apply materials by name.

Example for skeletal mesh containing more than 1 material

Ok, now let’s explore the material instance.

Human body material instance

This can be even more complicated to look at, but we can try simplify it and just implement the basics and iterate over it.

I would suggest opening 2 materials side by side and comparing what’s changed. For example, the material above is from human body when not equipping any items.

Below is when equipping brown cloth items.

Material when equipping brown cloth

So we can see that Body_D is consistent – i.e. this is effectively the natural skin color for the skeletal mesh then.

The other pieces, such as Chest, Gloves, Pants are materials for individual items that the character has equipped.

This means that when ‘drawing’ the character mesh, we always need to:

  • fetch correct individual skeletal meshes
  • compose a correct material instance, overriding relevant texture maps based on items
  • applying correct material to skeletal meshes using slot names

Building mesh and material resolver

Ok now we will start building the skeletal mesh and material resolvers.

To help with it, I created 2 models: CharacterAppearance struct and AppearanceKey struct.

CharacterAppearance and AppearanceKey structs

The CharacterAppearance struct simply tries to encapsulate ALL options that we can define in the character selection process. This is directly linked to the options we created in part 2.

CharacterAppearance struct

The appearance key is a simply composite key that we’ll use in Maps to fetch the data we desire.

Appearance key structure

Remember that when looking at material, we had material for skin color and we also needed to evaluate material for cloth.

This means we need at least 2 parameters to determine the material, the base skin option and the item that we have equipped. Hence BaseKey and ItemId. This could potentially be expanded in future.

I now created a new blueprint function library in the Characters/Appearance folder which we will use in character creation AND to resolve character appearance for in-game characters. The blueprint is called AppearanceResolver.

Creating new Blueprint function library

The content of this class is as follows:

Appearance resolver blueprint

So you can see in this example, I have ResolveHairMesh which has an input of the CharacterAppearance struct. We could’ve had the key directly, but to keep the input/output of these functions closer together I made it like this.

The output for a mesh resolver is a Skeletal Mesh. Note we also build the Material resolvers in some of the functions, which we will cover shortly.

You can see for the time being, I am not evaluating by ItemId. This is because in character creation screen I don’t yet need them, but when I will integrate it with my inventory system, I will expand the use here.

So the main objective is to create a local variable, containing all the data that you’ll require.

Hair meshes variable

So these variables will contain all the available options, including different races, genders, etc.

Let’s have a look at few other functions.

Find available chest pieces

Here I simply used the gender to evaluate the skeletal mesh. This is one of the reasons I passed in the Character Appearance struct instead of the Key. This will allow me to change this in future fast and easy.

So I’d suggest you to simplify it to your requirements to potentially avoid duplicate entries. i.e. for my races (human and undying) actually share same skeletal mesh, but have different material options.

Let’s have a look now at the material evaluators, we can start with more odd one:

Evaluate hair material

You can see here that the resolve hair color actually returns two materials.

This is because some styles require one type of hair material, and other styles require another. This is potentially an odd limitation of the asset, but let me quickly demonstrate.

Hair material for Hair_01
Hair material for Hair_02

So for me it was simply easier to locate both at all times and apply based on slot name, which only will apply relevant material. This will be covered below, when we’re applying skeletal meshes and materials to our character.

But I want to highlight that you can modify these functions to your requirements, stay flexible!

The hair materials variable contains the following

Hair materials

And again we can see the base key is directly connected to the hair options that we setup in the options before.

Let’s look at a more simple material resolver – face material resolver.

Face material resolver

And again a more complicated piece – body material evaluator.

Evaluate body material

The reason its more complicated is because we use the one material instance to apply to multiple different skeletal meshes. However that one material instance contains multiple texture sets.

For the character creation screen, I only want to modify the body skin tone. Therefore I pass in the character appearance structure AND the material instance that’s currently set. Then I evaluate what the skin texture should be, based on selected options and override that texture in the material instance, before passing it back.

Applying the options on the character

Now go back to the BP_Create_Character and I would suggest creating a new graph for this work, I called mine AppearanceModifierGraph. It will be responsible for updating all appearance options.

Add new graph to keep logic separated

Ok in this graph, we will need to create a new custom event to Resolve All Appearance.

Resolve all appearance blueprint

These custom event calls will not exist yet, but that’s what we’re going to be building now. Each piece of the mesh will need a custom resolver.

We’ll begin with Character Resolve Hair. This is perhaps one of the more complex ones.

Resolve Hair

There’s 4 things we’re doing

  • getting hair skeletal mesh, apply it
  • get hair color, we obtain 2 materials, apply them both
  • Get brow mesh, which includes beard, apply it
  • Resolve brow/beard color (based on hair color above)

They are numbered 1-4 above respectively.

The reason why its a bit more complex is because we fetch 2 different materials and apply 2 of them to the different slots. In this case we’re actually only using 1 of them, but it is possible that you’d need two, so its good to see it in practice anyway.

Furthermore, I’d like to maintain the beard/brow color to be the same as the hair color, hence its integrated here. In practice, you could have a separate call for that too.

Let’s look at the next example, resolving facial features – a bear in our case.

Resolve facial features

We can see this is more straight forward. We fetch one skeletal mesh, then we fetch the desired material for it and apply.

Then we have resolve face:

Resolve face

And the rest of the resolvers will now follow the same pattern:

Ears, feet, chest resolvers
Resolve hands, legs, calves and bracers

So basically for each modular piece:

  • get the skeletal mesh
  • set the skeletal mesh to correct component
  • get the material
  • apply material to the component (by slot name)

In our case, the body material is consistent, because the appearance struct holds all the necessary values. But you can be obtaining it individually as with skeletal mesh if your requirements are different, using the same technique.

The hard work is now complete and we just need to reference this back into the character creation widget.

Prepare Dynamic Material Instance

You may find the Material Instance Dynamic variable used in certain places, its prepared as part of constructor like so:

Prepare dynamic material instance on your character

This simply creates a dynamic material instance that we can use on the go, and populates the default values within.

For me, I am able to find some default values by checking an example:

This essentially tells me which values I need to set.

So, some functions are simply overriding the materials on this one, such as chest resolver.

Character creation widget addition

So going back to the Create Character Blueprint (where you spawned the character blueprint from).

Here you want to populate your Character appearance struct, this was briefly introduced in Building mesh and material resolver section.

The struct contains all the properties from the selection widget. So anything that could potentially impact the characters appearance.

Character Appearance struct

Then in the blueprint populate all fields from the options you have currently selected.

Populating the options for the update character appearance.

Notice that at the end, we call the function from the character blueprint to resolve all appearance, which references all the functions that you’ve built in the previous steps.

Note that its very likely I will be adding the item object(s) to the Appearance struct as well, to reference them in the resolvers. I have not determined the best way to do that yet (currently I think Map<String, Item> will probably be ideal, as I can specify which component the item will be adjusting. But this is not essential for the character creation part, but will be important quite soon, when integrating with the inventory.

In the next post I will look to integrate this work with the backend custom server and perhaps make a very basic character selection screen.

8 Comments

Comments are closed