I have tried LineTraceSingleByChannel and it works as I expect - it hits the child objects and the root.
The thing is I’m trying to just trace this one particular mesh component if possible.
I made a small example project showing the issue. Here’s 4 line traces done in different ways. The green ones worked the red ones didn’t. I’ll post my code below as well.
This is an actor I made that is implemented by a blueprint that sets the 2 meshes as cubes to reproduce:
// Header
#pragma once
#include "CoreMinimal.h"
#include "WeldedBody.generated.h"
UCLASS(Blueprintable)
class AWeldedBody : public AActor {
GENERATED_BODY()
public:
AWeldedBody(const FObjectInitializer& objInitializer);
virtual ~AWeldedBody() { }
virtual void BeginPlay() override;
virtual void Tick(float deltaSeconds) override;
protected:
UPROPERTY(EditAnywhere)
class UStaticMeshComponent* _rootMesh = nullptr;
UPROPERTY(EditAnywhere)
class UStaticMeshComponent* _childMesh = nullptr;
};
// Cpp
#include "WeldedBody.h"
AWeldedBody::AWeldedBody(const FObjectInitializer& objInitializer) : Super(objInitializer) {
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.bStartWithTickEnabled = true;
_rootMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("RootMesh"));
SetRootComponent(_rootMesh);
_childMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ChildMesh"));
_childMesh->AttachToComponent(GetRootComponent(), FAttachmentTransformRules::KeepRelativeTransform);
}
void AWeldedBody::BeginPlay() {
Super::BeginPlay();
_rootMesh->SetSimulatePhysics(true);
_rootMesh->SetEnableGravity(true);
_rootMesh->SetCollisionEnabled(ECollisionEnabled::Type::QueryAndPhysics);
_rootMesh->SetNotifyRigidBodyCollision(true);
_childMesh->SetCollisionEnabled(ECollisionEnabled::Type::QueryAndPhysics);
_childMesh->SetNotifyRigidBodyCollision(true);
}
void AWeldedBody::Tick(float deltaSeconds) {
Super::Tick(deltaSeconds);
// Record some convenient locations
FVector childLocation = _childMesh->GetComponentTransform().GetLocation();
FVector topOfChild = childLocation + 200 * FVector(0, 0, 1);
FVector rootLocation = GetActorLocation();
FVector topOfRoot = rootLocation + 200 * FVector(0, 0, 1);
// LineTraceComponent: Trace child directly at child's location
FHitResult hitResult;
FVector start = topOfChild;
FVector end = childLocation;
FCollisionQueryParams params;
if (_childMesh->LineTraceComponent(hitResult, start, end, params)) {
DrawDebugLine(GetWorld(), start, end, FColor::Green, false, 0.0f, 0, 5.0f);
} else {
DrawDebugLine(GetWorld(), start, end, FColor::Red, false, 0.0f, 0, 5.0f);
}
// LineTraceComponent: Trace root at child's location (slightly to the right so you can see both traces)
start = topOfChild + FVector(20, 0, 0);
end = childLocation + FVector(20, 0, 0);
if (_rootMesh->LineTraceComponent(hitResult, start, end, params)) {
DrawDebugLine(GetWorld(), start, end, FColor::Green, false, 0.0f, 0, 5.0f);
} else {
DrawDebugLine(GetWorld(), start, end, FColor::Red, false, 0.0f, 0, 5.0f);
}
// LineTraceComponent: Trace root at root's location
start = rootLocation;
end = topOfRoot;
if (_rootMesh->LineTraceComponent(hitResult, start, end, params)) {
DrawDebugLine(GetWorld(), start, end, FColor::Green, false, 0.0f, 0, 5.0f);
} else {
DrawDebugLine(GetWorld(), start, end, FColor::Red, false, 0.0f, 0, 5.0f);
}
// LineTraceSingleByChannel: Try tracing with LineTraceSingleByChannel
start = topOfChild + FVector(-20, 0, 0);
end = childLocation + FVector(-20, 0, 0);
FHitResult result;
FCollisionResponseParams responseParams;
if (GetWorld()->LineTraceSingleByChannel(result, start, end, ECC_WorldDynamic, params, responseParams)) {
DrawDebugLine(GetWorld(), start, end, FColor::Green, false, 0.0f, 0, 5.0f);
} else {
DrawDebugLine(GetWorld(), start, end, FColor::Red, false, 0.0f, 0, 5.0f);
}
}