I this is in a replicated Function on the character
the problem is that the TakeDamage is called around 10 times making the character die instantly but when i trace for other objects like the FLOOR it only prints the string 1 time like it should
I want the take damage function to only call once for the character
TArray<AActor*> ActorsToIgnore;
AActor* SourceActor = this;
if (!SourceActor)
{
// Hero is dead
return;
}
// this is use for other reasons
ActorsToIgnore.Add(SourceActor);
FCollisionQueryParams Params;
//Params.AddIgnoredActors(ActorsToIgnore);
TArray<FHitResult> HitResult;
FVector Start = RootComponent->GetComponentLocation();
GetWorld()->SweepMultiByChannel(HitResult, Start, Start, FQuat::Identity, ECC_GameTraceChannel4, FCollisionShape::MakeSphere(500.f), Params);
for (auto& LoopHitResult : HitResult)
{
if (LoopHitResult.GetActor() == SourceActor)
{
LoopHitResult.Actor->TakeDamage(20.f, FDamageEvent(), GetController(), this);
GEngine->AddOnScreenDebugMessage(-1, 3.f, FColor::Black, FString::Printf(TEXT("Hit: %s"), *LoopHitResult.Actor->GetName()));
}
}
You should consider drawing a debug sphere where you trace it, see how it looks in the scene, and check the collision settings of your components.
Also, it might be that both the actor and mesh components each have an associated FHitResult. You can confirm this by printing the display name of each primitive component for all the hit results.
A dirty way to solve this problem is just have a break statement after you trigger the damage once. This ensures it will only happen once, regardless of whats happening behind the scenes.
I made a new sphere component attached to the character , this component is the only one in the game that has the custom collision channel That the SphereTraceMulti traces for. but it still happens more then once it only happens twice now not 10 but i only want it happening 1 time
Is your character’s collisions settings set to block or overlap with the ECC_GameTraceChannel4 channel? You can check in your project’s collision settings. I would expect to see this sort of behavior if it was set to overlap rather than block.
Also is there a reason you’re calling SweepMultiByChannel and not something simpler?
I’m going to assume its happening twice without a break statement. Imagine you have two circles that intersect each other. They will share two points, if it isn’t the edge case. In the 3D case you will get a surface overlap, but it will just be points if you are dealing with unfilled volumes.
I very much recommend drawing the sphere with DrawDebugSphere() from “DrawDebugHelpers.h”. You will see the overlap points. Then post the picture. Text output is useful, but it really helps to see the traces.
If you read the documentation on SweepMultiByChannel you’ll notice that it says “return all initial overlaps using a specific channel (including blocking) if requested, then overlapping hits and then first blocking hit”. Since your character only overlaps with this trace channel that means your sweep is going to keep passing through your character, returning an event for every physical body in the character that it overlaps with. If you want to only have one event be returned, either set the trace channel to block on your character or use a different trace/sweep function.
Maybe you can check to see which components/bones are in each hit result returned. That might provide some clues as to what is going on. You can then use that information to double check all your collision settings on each bone/component, you might have multiple problems going on.
I think I understand what you’re trying to do a bit better now. Unreal’s damage system actually has a built in function to do what you’re trying to do, it’s called Apply Radial Damage.
You should be able to see where the crash happened in the stacktrace in the crash popup window. Alternatively you could build the visual studio project for “Development Editor” target and debug locally, then recreate the crash. I suspect it might be the case that your cast to AShooterCharacter might be failing, leading to dereferencing null pointers later on.