How to properly 'revive' a USkeletalMesh asset after calling PreEditChange() on it

Hi, I’m doing something to create and modify (in the editor only) a USkeletalMesh asset that USkeletalMeshComponents are using in the scene. Without calling PreEditChange, the ‘create’ part works fine (i do it in PostLoad of my custom Asset), but once i start modifying (in PostEditChangeProperty of my custom Asset), I get assertion failures and crashes in the rendering code, which is understandable since I’m “pulling the rug” of the rendering assets while they’re being rendered. So, to properly clear the rendering data out, i call PreEditChange(NULL) on the USkeletalMesh, then PostEditChange() after im done modifying. This should recreate all it’s rendering data (and, by browsing the code, also refresh all USkinnedMeshComponents which use it), but my mesh is still invisible. I even tried doing what FbxImporter does and using FComponentReregisterContext after PostEditChange on the components that use it, but that changes nothing.

How do i properly revive my mesh after changes ?

Here is my code:

		USkeletalMesh* targetMesh = GetGeneratedMesh(); //this retrieves a TSubobjectPtr USkeletalMesh that this Asset owns.

		//mergeMeshes is a TArray<USkeletalMesh*> of existing, proper USkeletalMeshes
		TArray<FSkelMeshMergeSectionMapping> emptySections;
		FSkeletalMeshMerge merger(targetMesh,mergeMeshes,emptySections,0);

		targetMesh->PreEditChange(NULL); //if i comment this line out, then the mesh appears properly on load, but crashes/asserts the editor on change
		const bool mergeStatus = merger.DoMerge();
		check(mergeStatus == true);
		targetMesh->PostEditChange(); //also comment this one out with PreEditChange

		// Now iterate over all skeletal mesh components re-initialising them.
		// This shouldn't be necessary because USkeletalMesh::PostEditChange does it internally ?
		for (TObjectIterator<USkeletalMeshComponent> It; It; ++It)
		{
			USkeletalMeshComponent* SkelComp = *It;
			if (SkelComp->SkeletalMesh == targetMesh && SkelComp->GetScene())
			{
				FComponentReregisterContext ReregisterContext(SkelComp);
			}
		}

It seems that the culprit is something related to this in SkeletalMesh.cpp

// rebuild vertex buffers
uint32 VertexFlags = GetVertexBufferFlags();
for( int32 LODIndex = 0;LODIndex < Resource->LODModels.Num();LODIndex++ )
{
Resource->LODModels[LODIndex].BuildVertexBuffers(VertexFlags);
}

So it seems my problem was only because i was using FSkeletalMeshMerge and what it does is merge the output to the Vertex Buffer, not the source rigid/soft vertices that BuildVertexBuffers expects. Adding a small preamble to BuildVertexBuffers makes FSkeletalMeshMerge work.

void FStaticLODModel::BuildVertexBuffers(uint32 BuildFlags)
{
	int32 totalChunkVerts = 0;
	for(const auto& chunk : Chunks)
	{
		//use array sizes, since the size variables have the expected number even if arrays are empty
		totalChunkVerts += chunk.RigidVertices.Num() + chunk.SoftVertices.Num();
	}

	//rebuild only if we have source data to use
	if (totalChunkVerts > 0 || VertexBufferGPUSkin.GetNumVertices() != this->NumVertices)
	{
		bool bUseFullPrecisionUVs = (BuildFlags & EVertexFlags::UseFullPrecisionUVs) != 0;
		bool bHasVertexColors = (BuildFlags & EVertexFlags::HasVertexColors) != 0;

		original code for rebuild vertex buffer and vertex color buffer here
	}

	if( HasApexClothData() )
	    original code for rebuild apex cloth data here
}