How to use line trace with skeletal meshes?

Can’t seem to get a material name from a line trace hit on a skeletal mesh. I only can on a static mesh.

Goal: To highlight a material that a mouse is over.

Approach:
I’ve defined materials on the mesh in a 3d modeling suite.
I can access materials from the line trace like in the pic.
However, line traces are only working with static meshes, not skeletal meshes. Is there a setting?

Things I’ve tried:
Setting trace complex on line trace (necessary to get material).
Creating physics asset for skeletal mesh.
Changing the collision settings on the skeletal mesh.

After creating a physics asset, the line trace is stopped by the mesh, but no material name is shown. However, material names are shown on static meshes.

Hitting the same issue. Were you ever able to figure this one out?

Unfortunately “Face Index” is never going to be returned for a skeletal mesh (it will be -1) , so your material lookup will fail.

In fact, in my experience it is only ever going to work for (non physical) static meshes. The reason is that despite the fact that you have ‘trace complex’ enabled, traces can only ever collide with the skeletal mesh’s physics asset bodies, not the literal triangles on the skeletal mesh itself.

This is actually a pretty annoying limitation of the underlying PhysX implementation. What would be great is if there was some way it could ‘convert’ the impact position on the physics body to a position on the tri mesh, in order to get a face index.

Does anyone at Epic have a workaround for this?

Bumping this. I wonder why there is still no way to do this for such an important feature.

well at least I feel better, thought I was really missing something even set up debugger I am new :slight_smile: and can see it doesn’t even notice the AI Skeleton i have (Chicken) shows hit target is landscape, or a box or any static mesh but it is annoying :slight_smile: i don’t even know what to call stuff

You can get the Material of a line trace hit, or rather, where the closest vertex index is to a line trace hit.
It requires some c++ but it isn’t too hard.

Firstly get all meshVertexPositions by calling ComputeSkinPositions, example from my code where meshVertexPositionsArray is a TArray defined in .h:

	TArray<FMatrix> matrixArrayTemp;
	const FSkeletalMeshLODRenderData& skelMeshRenderDataTemp = vertexPaintSkelComponent->GetSkeletalMeshRenderData()->LODRenderData[0];
	FSkinWeightVertexBuffer& skinWeightBufferTemp = *vertexPaintSkelComponent->GetSkinWeightBuffer(0); // Får crash med array out of bounds 46 of 0

	vertexPaintSkelComponent->CacheRefToLocalMatrices(matrixArrayTemp);

	vertexPaintSkelComponent->ComputeSkinnedPositions(vertexPaintSkelComponent, meshVertexPositionsArray, matrixArrayTemp, skelMeshRenderDataTemp, skinWeightBufferTemp);

Then you loop through them to check the distance from the line trace Hit Location and save the closest index. Remember that the meshVertexPositions you get is local to the skeletal mesh component, not to the actor local space which is why i do some transforms here. Looping through them in code is not as expensive as you may think, this is from a vertex color and detection plugin where i’ve stresstested looping through 48k verts from paragon characters every frame and worked well:

FVector hitLocationInActorLocalTemp = UKismetMathLibrary::InverseTransformLocation(actor->GetTransform(), paintOnMeshSettings.location);

for (int i = 0; i < meshVertexPositionsArray.Num(); i++) {

meshVertexInActorLocalSpaceTemp = UKismetMathLibrary::InverseTransformLocation(actor->GetTransform(), UKismetMathLibrary::TransformLocation(vertexPaintSkelComponent->GetComponentTransform(), meshVertexPositionsArray[i]));

			if ((hitLocationInActorLocalTemp - meshVertexInActorLocalSpaceTemp).Size() < closestDistanceTOClosestVertexTemp) {

				closestDistanceTOClosestVertexTemp = (hitLocationInActorLocalTemp - meshVertexInActorLocalSpaceTemp).Size();

				closestVertIndexTest = i;
			}

}

Then you get section from vertex index and just use GetMaterial :

const FSkeletalMeshLODRenderData& skelMeshRenderDataTemp = skelMesh->GetSkeletalMeshRenderData()->LODRenderData[0];

int sectionIndexTemp;
int verIndexTemp;

skelMeshRenderDataTemp.GetSectionFromVertexIndex(vertIndex, sectionIndexTemp, verIndexTemp);

return skelMesh->GetMaterial(skelMeshRenderDataTemp.RenderSections[sectionIndexTemp].MaterialIndex);

Hope this helps!

2 Likes