Despite having the ability to set a namespace for DataAssetLinks in a SkeletalMesh, there seems to be no way to retrieve specific Data Assets in a Blueprint. I can access them from a ControlRig using a GetUserData node, but a similar node does not exist in a regular Blueprint. Is there any way to fetch DataAssetLinks by namespace within a Blueprint?
Steps to Reproduce
- Create a SkeletalMesh asset.
- In the Asset Details panel, under the SkeletalMesh header, find Asset User Data.
- Add up to 3 array elements and set each one to Data Asset Link.
- Give each one a unique namespace and Data Asset.
- Create a Blueprint Actor and add a SkeletalMeshComponent. Assign the SkeletalMesh you just created to that component.
- Navigate to the EventGraph and create a GetAssetUserDataOfClass node. Plug it into BeginPlay and attach your SkeletalMeshComponent into the Target input parameter. Set the InUserDataClass to NamespacedUserData.
- Connect the output of that node to a CastToDataAssetLink node.
- From the output parameter of the cast node, get the DataAsset and connect it to a LoadAssetBlocking node.
- Print the output of the LoadAssetBlocking node to see the returned DataAsset. Note that it only ever returns the first DataAsset assigned in your SkeletalMesh.
Hi, the intention with asset user data, in general, is that there should only be one per type. That’s why, if you look at one of the implementations of AddAssetUserData (like SkeletalMesh::AddAssetUserData), you’ll see that we remove any existing user data of that type before adding the new user data. That’s also why, like you noticed, the GetAssetUserDataOfClass function only returns a single value. It’s an oversight in the Skeletal Mesh editor UI that you can add multiple user data of the same type, since that goes directly to the property rather than calling AddAssetUserData.
I’d be interested to know what the use case is for having more than one type of the same data? I can talk to the dev team about whether we should relax the requirement and support multiple entries per type.
If you’re relying on the current behaviour, the best option in the short term is likely going to be to implement a blueprint library method for your project that returns an entry based on the namespace string you pass. You could do that via GetAssetUserDataArray and then filter the array you get back.
Thanks for the answer, Euan. My original intention was to use one Data Asset to store parameters and values that can be read in the creation of character-specific Control Rigs - very similar to the setup discussed at Unreal Fest 2024. The second Data Asset was to be used for armor-specific lighting scenarios. Since we are using Mutable, we needed a way to identify which armor a character had equipped and which lights should be spawned with it. I setup a Data Asset to contain this information, to include ParentSocket, OffsetTransform, LightType, and LightSettings. Since the SK has the ability to add multiple Data Asset Links separated by namespace, I thought it would be a good solution. However, as we’ve seen, this does not work as I expected.
Thanks for the extra info on this. I see that the Control Rig implementation has multiple different forms of user data, one of which comes from IInterface_AssetUserData (like the skeletal mesh asset), but there’s also UControlRig::CombinedAssetUserData which is an aggregation of user data from the rig and the various assets that the rig references (including the skeletal mesh). And it’s CombinedAssetUserData that you’re accessing via the rig unit that’s mentioned in the UE Fest video.
I don’t think there’s anything inherently wrong with what the Control Rig implementation is doing, but it is going to behave differently from the other asset types that support asset user data in the engine. And unfortunately, if we ever were to prevent you adding multiple user datas of the same type via the skeletal mesh editor, that would break your current workflow. Having said that, it’s somewhat unlikely we would do that if it’s a common workflow that Control Rig users are making use of.
Would you be able to do what you need with Mutable using just one piece of user data per-type on the skeletal mesh, or do you need to have multiple? If you do need to have multiple, the blueprint library method may be the best option to expose the data to regular blueprint.
I already moved to a single Data Asset workflow for Mutable that contains a list of parameters as described in my last post. It seems to work well, but I’m running into other issues at the moment regarding Mutable. I can query the skeletal mesh and its assigned Data Asset for the attachment but only if I cast it to a Mesh Component. However, when I do that, the specific pieces are no longer following the body. I’m in the process of troubleshooting that, but the single Data Asset works well for my needs.
Just wanted to check in to see if you’d managed to get this working, or if you need any help with the Mutable specific part of the setup?
I have the Data Asset part working, but the Mutable side of the equation is still unresolved. I want to dynamically query the SkeletalMesh assigned to a given parameter - in this case, a piece of armor. In order to expose the SkeletalMesh, I need to cast the MeshSections to a MeshComponent node instead of an AddToMeshComponent node, which is what I’m currently doing. Unfortunately, when I assign the pieces as MeshComponents and attach that component to the BaseObject, the pieces no longer follow the body. If I go this route, does this mean that I will have to create SkeletalMeshComponents in the Blueprint and then dynamically set the SkeletalMeshAsset? I had hoped to avoid doing this to keep my Blueprint light.
To be honest, the thing that would be most helpful is if there was a way in the CustomizableObject to snap objects to sockets. Aside from lights, I also need to add accessories to the character eventually. Typically, I would have the art team make an asset at the origin and then snap it to sockets so they only have to create one version of it. Unfortunately, I don’t see a way of doing that in Mutable, which means I either need a BP solution or ask the art team to create multiple versions of the same asset for each configuration. In this case, let’s imagine I have a pouch that can be equipped in 4 different spots. With the traditional approach, I only need one SM or SK pouch. With Mutable currently, I need 4 SK pouches (without additional BP logic).
Hi, sorry for the delay following up. I got pulled onto other work last week and the long weekend here also slowed things down.
I took a look at the issue you described with the AddToMeshComponent vs MeshComponent node and also talked with the Mutable team about that. If the sections are all added via the same MeshComponent node then they should behave the same as when added via AddToMeshComponent, so this sounds like you may be running into a bug. If you can show how you have the graph setup, that could be useful in terms of trying to get a repro.
For the second part about being able to attach meshes to sockets, that’s something that’s been requested previously but as you’ve seen, it’s not supported at the moment since you can’t interrogate the skeleton from the CO graph. The usual recommendation here is to pipe in the socket transforms as variables and then use the TransformMeshInMesh node to move the mesh to the correct location (that node is experimental so there can be issues with it). Or an alternative is to use the PoseMesh node to drive the bone that the mesh is skinned to via a Pose Asset. This is discussed briefly in one of the talks from UE Bali we just added to youtube here.
Thanks Euan! I also got caught up with a lot of other work, so I apologize for the delay. But that info is definitely helpful. I did some preliminary tests and found that it worked fairly well for what I need at the moment.
Good to hear that was useful! Would you like me to close off this thread, or should we keep it open in case you have further questions (it’ll auto-close after a few weeks)?
I think I have what I need for this issue. Thanks for all the help! We can go ahead and close this ticket.