/* * Spawns the hitbox and processes the actors within it */ void AHero::AttackTrace() { //Actors that overlap the box stored in this array TArray<struct FOverlapResult> OutOverlaps; //Orient the box in the direction of the character FQuat Rotation = Instigator->GetTransform().GetRotation(); FVector Start = Instigator->GetTransform().GetLocation() + Rotation.Rotator().Vector() * 100.0f; FCollisionShape CollisionHitShape; FCollisionQueryParams CollisionParams; //Have the hitbox ignore the player CollisionParams.AddIgnoredActor(Instigator); //Set what will respond to the collision FCollisionObjectQueryParams CollisionObjectTypes; CollisionObjectTypes.AddObjectTypesToQuery(ECollisionChannel::ECC_PhysicsBody); CollisionObjectTypes.AddObjectTypesToQuery(ECollisionChannel::ECC_Pawn); CollisionObjectTypes.AddObjectTypesToQuery(ECollisionChannel::ECC_WorldStatic); //Create the hitbox and get the actors within CollisionHitShape = FCollisionShape::MakeBox(FVector(100.0f, 60.0f, 0.5f)); GetWorld()->OverlapMulti(OutOverlaps, Start, Rotation, CollisionHitShape, CollisionParams, CollisionObjectTypes); //Process all hit actors for (int i = 0; i < OutOverlaps.Num(); i++) { if (OutOverlaps[i].GetActor() && !HitActors.Contains(OutOverlaps[i].GetActor())) { //Check if hit registered GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("hit")); //Now call the function that does something to our unfortunate actor... ProcessHitActor(OutOverlaps[i].GetActor()); } } }
void ABaseCharacter::CheckAttackOverlap(){ //Overlapping actors for each box spawned will be stored here TArray<struct FOverlapResult> OutActorOverlaps; //Hit other actors only once TArray<AActor*> ProcessedActors; //The initial rotation of our box is the same as our character rotation FQuat Rotation = GetTransform().GetRotation(); FVector Start = GetTransform().GetLocation() + Rotation.Rotator().Vector() * 100.0f; FCollisionShape CollisionHitShape; FCollisionQueryParams CollisionParams; //We do not want the character to hit itself, don't store this character in the array, to ignore it's collision CollisionParams.AddIgnoredActor(this); //Set the channels that will respond to the collision FCollisionObjectQueryParams CollisionObjectTypes; CollisionObjectTypes.AddObjectTypesToQuery(ECollisionChannel::ECC_PhysicsBody); CollisionObjectTypes.AddObjectTypesToQuery(ECollisionChannel::ECC_Pawn); //CollisionObjectTypes.AddObjectTypesToQuery(ECollisionChannel::ECC_WorldStatic); // uncomment to enable bashing objects //Create the box and get the overlapping actors CollisionHitShape = FCollisionShape::MakeBox(AttackBox); GetWorld()->OverlapMulti(OutActorOverlaps, Start, Rotation, CollisionHitShape, CollisionParams, CollisionObjectTypes); AActor* ActorToProcess; //Process all hit actors for (int i = 0; i < OutActorOverlaps.Num(); ++i) { ActorToProcess = OutActorOverlaps[i].GetActor(); //We process each actor only once per Attack execution if (ActorToProcess && !ProcessedActors.Contains(ActorToProcess)) { //Add this actor to the array because we are spawning one box per tick and we don't want to hit the same actor twice during the same attack animation ProcessedActors.AddUnique(ActorToProcess); if ( dynamic_cast<APatrollingEnemyCharacter*>(ActorToProcess) ){ APatrollingEnemyCharacter* ennemy = (APatrollingEnemyCharacter*)ActorToProcess; ennemy->OnHit(this); } } } }
AActor* AMagnetTile::GetMagnetHitActor( FHitResult& hit ) { FCollisionQueryParams queryParam; queryParam.bFindInitialOverlaps = false; queryParam.bReturnFaceIndex = true; FCollisionObjectQueryParams objectParam; objectParam.AddObjectTypesToQuery( ECollisionChannel::ECC_Pawn ); objectParam.AddObjectTypesToQuery( ECC_Portal ); auto pos = TileMesh->GetSocketLocation( "Socket" ); auto rayStart = pos + GetClampedForwardVector() * 2.0f; auto laserVector = GetClampedForwardVector( true ); GetWorld()->LineTraceSingleByObjectType( hit , rayStart , pos + laserVector , objectParam , queryParam ); magnetEndPos = hit.ImpactPoint; return hit.Actor.Get(); }
void AAmbitionOfNobunagaPlayerController::PlayerTick(float DeltaTime) { Super::PlayerTick(DeltaTime); if(Hud) { CurrentMouseXY = GetMouseScreenPosition(); TArray<FHitResult> Hits; bool res; FVector WorldOrigin; FVector WorldDirection; FCollisionObjectQueryParams CollisionQuery; CollisionQuery.AddObjectTypesToQuery(ECC_WorldStatic); if (UGameplayStatics::DeprojectScreenToWorld(this, CurrentMouseXY, WorldOrigin, WorldDirection) == true) { res = GetWorld()->LineTraceMultiByObjectType(Hits, WorldOrigin, WorldOrigin + WorldDirection * HitResultTraceDistance, CollisionQuery); } // 只trace 地板的actor // 地板名可以自定義 FVector HitPoint(0, 0, 0); if (Hits.Num() > 0) { for (FHitResult Hit : Hits) { if (Hit.Actor.IsValid() && Hit.Actor->GetFName().GetPlainNameString() == FloorActorName) { HitPoint = Hit.ImpactPoint; } // all landscape can click if (Hit.Actor.IsValid()) { FString ResStr; Hit.Actor->GetClass()->GetName(ResStr); if (ResStr == "Landscape") { HitPoint = Hit.ImpactPoint; } } } } Hud->OnMouseMove(CurrentMouseXY, HitPoint); } }
vector<AGameObject*> APlayerControl::ComponentPickExcept( AGameObject* object, UPrimitiveComponent* up, vector<AGameObject*> except, FString queryObjectType, vector<FString> intersectableTypes ) { FComponentQueryParams fqp; except += object; // this will cause the object to pick itself if you don't put it in the except group for( AGameObject* o : except ) if( o ) fqp.AddIgnoredActor( o ); FCollisionObjectQueryParams objectTypes = FCollisionObjectQueryParams( FCollisionObjectQueryParams::InitType::AllObjects ); for( FString channelName : intersectableTypes ) { ECollisionChannel channel = CollisionChannels[channelName]; objectTypes.AddObjectTypesToQuery( channel ); // Channel 3 is the RESOURCES channel. } TArray<FOverlapResult> overlaps; FRotator ro = up->GetComponentRotation(); FVector ve = up->GetComponentLocation(); // QUERY on channel ECollisionChannel queryChannel = CollisionChannels[queryObjectType]; GetWorld()->ComponentOverlapMultiByChannel( overlaps, up, ve, ro, queryChannel, fqp, objectTypes ); map<float, AGameObject*> objects; for( int i = 0; i < overlaps.Num(); i++ ) { if( AGameObject* go = Cast<AGameObject>( overlaps[i].GetActor() ) ) { float d = FVector::Dist( object->Pos, go->Pos ); objects[ d ] = go; } } return MakeVectorS( objects ); }
// Check for bullet collisions void AMurphysLawCharacter::ComputeBulletCollisions() { // Only look for pawns FCollisionObjectQueryParams CollisionObjectQueryParams; CollisionObjectQueryParams.AddObjectTypesToQuery(ECollisionChannel::ECC_PhysicsBody); CollisionObjectQueryParams.AddObjectTypesToQuery(ECollisionChannel::ECC_Destructible); CollisionObjectQueryParams.AddObjectTypesToQuery(ECollisionChannel::ECC_WorldStatic); // Remove self from query potential results since we are the first to collide with the ray FCollisionQueryParams RayQueryParams; RayQueryParams.AddIgnoredActor(this); // Ray starting coordinates const FVector CollisionRayStart = GetFirstPersonCameraComponent()->GetComponentLocation(); const FVector CollisionRayInitialDirection = GetFirstPersonCameraComponent()->GetComponentTransform().GetRotation().GetAxisX(); // Group damage of touched objects together const float MaxFragmentDeviationRadian = FMath::DegreesToRadians(GetEquippedWeapon()->GetMaxFragmentDeviationAngle(IsCharacterAiming)); bool AtLeastOneHit = false; // Trace lines to detect pawn for (int32 i = 0; i < GetEquippedWeapon()->GetNumberOfEmittedFragments(); ++i) { // Ray ending coordinates const FVector CollisionRayAngledDirection = FMath::VRandCone(CollisionRayInitialDirection, MaxFragmentDeviationRadian); const FVector CollisionRayEnd = CollisionRayStart + (CollisionRayAngledDirection * GetEquippedWeapon()->GetMaxTravelDistanceOfBullet()); FHitResult CollisionResult; bool HasHit = GetWorld()->LineTraceSingleByObjectType(CollisionResult, CollisionRayStart, CollisionRayEnd, CollisionObjectQueryParams, RayQueryParams); if (HasHit) { // Simple damage amount considering the distance to the target depending on the bone hit float DeliveredDamage = GetDeliveredDamage(CollisionResult); FPointDamageEvent CollisionDamageEvent(DeliveredDamage, CollisionResult, CollisionRayAngledDirection, UDamageType::StaticClass()); // If the actor we hit is a hittable actor and an enemy, we have at least one hit so we'll show the Hit Marker if (IsHittableActor(CollisionResult.GetActor()) && !MurphysLawUtils::IsInSameTeam(CollisionResult.GetActor(), this)) { AtLeastOneHit = true; } if (Role == ROLE_Authority) { CollisionResult.GetActor()->TakeDamage(DeliveredDamage, CollisionDamageEvent, GetController(), this); } else { Server_TransferDamage(CollisionResult.GetActor(), DeliveredDamage, CollisionDamageEvent, GetController(), this); } } } // If there was at least one hit, we show the HitMarker if (AtLeastOneHit) { auto MyController = Cast<AMurphysLawPlayerController>(GetController()); if (MyController != nullptr && MyController->GetHUDInstance() != nullptr) { MyController->GetHUDInstance()->ShowHitMarker(); } } }