rlewicki / MeleeTrace

Unreal Engine plugin that enables user to accurately trace melee hits in the game using interpolation between sockets defined directly on the character or weapon mesh.
https://www.unrealengine.com/marketplace/en-US/product/melee-trace
MIT License
40 stars 8 forks source link

Component trace never starts #7

Closed Knear2 closed 4 months ago

Knear2 commented 5 months ago

My weapon it's his own blueprint character and keeps all the attack logic and the melee component, my character only calls it, however, when i attack, the line trace never starts, only seems to work if my weapon is attatched to the player. Here i attach a picutre of the logic inside of the weapon. screenshot

rlewicki commented 5 months ago

Hey @Knear2 thanks for reaching out. I'll have a look at the problem later tonight and will try to help you.

rlewicki commented 5 months ago

Okay, so case you are describing should work without any problems honestly. The trace component searches for ANY static or skeletal mesh components attached to the owner. So if the weapon is an actor itself and it has a static/skeletal mesh component and trace component it should find it.

Perhaps your weapon mesh doesn't have sockets with the names you define them? This is very important, otherwise the system will never start tracing. Here is a code snippet:

    TArray<UActorComponent*> MeshComponents;
    GetOwner()->GetComponents(UMeshComponent::StaticClass(), MeshComponents);
    for (UActorComponent* MeshComponent : MeshComponents)
    {
        UMeshComponent* TypedMeshComponent = Cast<UMeshComponent>(MeshComponent);
        check(TypedMeshComponent);
        if (TypedMeshComponent->DoesSocketExist(MeleeTraceInfo.StartSocketName)
            && TypedMeshComponent->DoesSocketExist(MeleeTraceInfo.EndSocketName))
        .
        .
        .

As you can see, both StartSocketName and EndSocketName must exist in selected mesh component for system to proceed to start tracing.

Let me know if you need any further help!

DawnDevelop commented 4 months ago

Hi, @rlewicki I guess what they mean is that they have a Blueprint which contains a skeletal mesh of the weapon with the sockets, and it is attached at runtime. For example, this is the Blueprint of my weapon:

image

Just for demo purposes, I attach it at runtime to my main player character: image

The current code creates an array with all components of the owner actor that are of type UMeshComponent or derived from UMeshComponent. The problem is that the Skeletal Mesh we want to get the socket from is inside the BP_Katana.

To get the Skeletal Mesh inside the Blueprint, we would need something like the following, where we also check the meshes inside attached actors. Here is my take on the updated code:

void UMeleeTraceComponent::StartTrace(const FMeleeTraceInfo& MeleeTraceInfo, uint32 TraceHash)
{
    AActor* Owner = GetOwner();

    TArray<UActorComponent*> MeshComponents;
    TArray<AActor*> ActorsToCheck = { Owner };
    TArray<AActor*> AttachedActors;

    Owner->GetAttachedActors(AttachedActors);
    ActorsToCheck.Append(AttachedActors);

    for (AActor* Actor : ActorsToCheck)
    {
        TArray<UActorComponent*> ActorMeshComponents;
        Actor->GetComponents(UMeshComponent::StaticClass(), ActorMeshComponents);
        MeshComponents.Append(ActorMeshComponents);
    }

    for (UActorComponent* MeshComponent : MeshComponents)
    {
        UMeshComponent* TypedMeshComponent = Cast<UMeshComponent>(MeshComponent);
        check(TypedMeshComponent);

        if (TypedMeshComponent->DoesSocketExist(MeleeTraceInfo.StartSocketName) 
            && TypedMeshComponent->DoesSocketExist(MeleeTraceInfo.EndSocketName))
        {
            FActiveMeleeTraceInfo& NewMeleeTraceInfo = ActiveMeleeTraces.AddDefaulted_GetRef();
            NewMeleeTraceInfo.MeleeTraceInfo = MeleeTraceInfo;
            NewMeleeTraceInfo.TraceHash = TraceHash;
            NewMeleeTraceInfo.SourceMeshComponent = TypedMeshComponent;
            GetTraceSamples(TypedMeshComponent, MeleeTraceInfo, NewMeleeTraceInfo.PreviousFrameSampleLocations);
            OnTraceStart.Broadcast(this);
            return;
        }
    }

    ensureAlwaysMsgf(false,
        TEXT("None of the USkeletalMeshComponents contain sockets with names: %s and %s"),
        *MeleeTraceInfo.StartSocketName.ToString(),
        *MeleeTraceInfo.EndSocketName.ToString());
}

It's not properly tested, but it works for me.

Thank you for your time and nice work on the Plugin!

DawnDevelop commented 4 months ago

I opened a PR if you want to have a look at the changes #11

rlewicki commented 4 months ago

@DawnDevelop ah I see it now. It's true I have not considered a case where a weapon is it's own child actor rather then simply a mesh attached to the owner.

Thanks for opening the pull request, I'll try to have a look at it today or tomorrow!