Download

Crash on SetSkeletalMesh

Hello,
I use the SetSkeletalMesh for set the mesh of my character.
The function work, but after a lot of time when the function is call, it’s crash randomely in the function SetSkeletalMesh but because of the index of bones like GetboneName(int32 index).

I call the function when my player is hit by my enemy.

The variable SkinsCharacter is all the SkeletalMesh who are going to be use by the character.

Example:
When the player have an helmet, I must not display the hair of the player to avoid texture bug. But when the player loose his helmet I must display his hair.

So I create multiple Skeletal Mesh and set them when I need it to avoid this probleme. SkinsCharacter is create with some FSkeletalMeshMerge.


bool UArmorManagerComponent::LosesArmor(USkeletalMeshComponent* mesh, TArray<USkeletalMesh*> SkinsCharacter)
{
    if (CurrentNbArmor > 0)
    {
        CurrentNbArmor--;

        if (CurrentNbArmor < SkinsCharacter.Num())
        {
            if (SkinsCharacter[CurrentNbArmor] != nullptr)
            {
                mesh->SetSkeletalMesh(SkinsCharacter[CurrentNbArmor], false);
            }
        }
        return true;
    }
    else
        return false;
}

Callstack on a crash will help.

Thanks for the answer.

As I said it’s a little bit random. So I send you 2 different Callstatck.


     [Cadre en ligne] UE4Editor-Core.dll!FGenericPlatformMemory::OnOutOfMemory::__l33::<lambda_e0a1bcd00d8233493e8185bf392a8a7d>::operator()() Ligne 212    C++
     UE4Editor-Core.dll!FGenericPlatformMemory::OnOutOfMemory(unsigned __int64 Size, unsigned int Alignment) Ligne 212    C++
     [Cadre en ligne] UE4Editor-Core.dll!FMallocTBB::OutOfMemory(unsigned __int64) Ligne 50    C++
     UE4Editor-Core.dll!FMallocTBB::Realloc(void * Ptr, unsigned __int64 NewSize, unsigned int Alignment) Ligne 140    C++
     UE4Editor-Core.dll!FMemory::Realloc(void * Original, unsigned __int64 Count, unsigned int Alignment) Ligne 52    C++
     [Cadre en ligne] UE4Editor-Engine.dll!FHeapAllocator::ForAnyElementType::ResizeAllocation(int) Ligne 384    C++
     UE4Editor-Engine.dll!TArray<unsigned char,FDefaultAllocator>::ResizeTo(int NewMax) Ligne 2475    C++
     [Cadre en ligne] UE4Editor-Engine.dll!TArray<unsigned char,FDefaultAllocator>::Empty(int) Ligne 1645    C++
     UE4Editor-Engine.dll!USkinnedMeshComponent::AllocateTransformData() Ligne 1365    C++
     UE4Editor-Engine.dll!USkeletalMeshComponent::AllocateTransformData() Ligne 2580    C++
     UE4Editor-Engine.dll!USkinnedMeshComponent::SetSkeletalMesh(USkeletalMesh * InSkelMesh, bool bReinitPose) Ligne 1315    C++
     UE4Editor-Engine.dll!USkeletalMeshComponent::SetSkeletalMesh(USkeletalMesh * InSkelMesh, bool bReinitPose) Ligne 2540    C++
     UE4Editor-Brawler3D.dll!UArmorManagerComponent::LosesArmor(USkeletalMeshComponent * mesh, TArray<USkeletalMesh *,FDefaultAllocator> SkinsCharacter) Ligne 102    C++

Maybe garbage collection issue. Is merged SkinsCharacter has UPROPERTY? Ensure SkinsCharacter is not pendingkill.



if (SkinsCharacter[CurrentNbArmor] != nullptr && SkinsCharacter[CurrentNbArmor].IsPendingKill() != false)
{
...


Ok when I try this code, the function doesn’t call SetSkeletalMesh(), so I don’t crash. But How can I avoid this garbage collection issue ?

SkinsCharacter isn’t an UPROPERTY.
I build the array like this.



if (Skeleton != nullptr && PlayerSkinsSkeletal.Num() > 0)
    {
        int sizeTarget = ABrawler3DCharacter::NbOfSkin;
        int sizeSkins = PlayerSkinsSkeletal.Num();

        for (int i{ 0 }; i < sizeTarget; i++)
        {
            TargetMerge.Add(NewObject<USkeletalMesh>());

            TargetMerge*->Skeleton = Skeleton;

            TArray<FSkelMeshMergeSectionMapping> EmptyArray;

            TArray<USkeletalMesh*> SkinsSkeletalTemp = PlayerSkinsSkeletal;
            for (int j{ 0 }; j < i; j++)
            {
                SkinsSkeletalTemp.RemoveAt(sizeSkins - (j + 1));
            }

            FSkeletalMeshMerge Merger(TargetMerge*, SkinsSkeletalTemp, EmptyArray, 0);

            if (!Merger.DoMerge())
            {
                GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("BadMerge")));
                UE_LOG(LogTemp, Warning, TEXT("Problem With the Skeletal Merge %d"), i);
            }
        }

        GetMesh()->SetSkeletalMesh(TargetMerge[2]);
    }


Use UPROPERTY to prevent garbage collection.

With optionally Transient for not be saved or loaded in this case.



UPROPERTY(Transient)
TArray<USkeletalMesh*> TargetMerge;

https://docs.unrealengine.com/en-US/…ons/index.html

This work I wait lot of time and when I call the function SetSkeletalMesh() don’t crash but when I keep :


 
 if (SkinsCharacter[CurrentNbArmor].IsPendingKill() != false) 

the function doesn’t call SetSkeletalMesh(), and I don’t understand why.