本文整理汇总了C++中FVector::IsZero方法的典型用法代码示例。如果您正苦于以下问题:C++ FVector::IsZero方法的具体用法?C++ FVector::IsZero怎么用?C++ FVector::IsZero使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在类FVector
的用法示例。
在下文中一共展示了FVector::IsZero方法的15个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。
示例1: FaceTowardSource
void AGameplayAbilityWorldReticle::FaceTowardSource(bool bFaceIn2D)
{
if (TargetingActor)
{
if (bFaceIn2D)
{
FVector FacingVector = (TargetingActor->StartLocation.GetTargetingTransform().GetLocation() - GetActorLocation()).GetSafeNormal2D();
if (FacingVector.IsZero())
{
FacingVector = -GetActorForwardVector().GetSafeNormal2D();
}
if (!FacingVector.IsZero())
{
SetActorRotation(FacingVector.Rotation());
}
}
else
{
FVector FacingVector = (TargetingActor->StartLocation.GetTargetingTransform().GetLocation() - GetActorLocation()).GetSafeNormal();
if (FacingVector.IsZero())
{
FacingVector = -GetActorForwardVector().GetSafeNormal();
}
SetActorRotation(FacingVector.Rotation());
}
}
}
示例2: AimWithPlayerController
void AGameplayAbilityTargetActor_Trace::AimWithPlayerController(const AActor* InSourceActor, FCollisionQueryParams Params, const FVector& TraceStart, FVector& OutTraceEnd, bool bIgnorePitch) const
{
if (!OwningAbility) // Server and launching client only
{
return;
}
APlayerController* PC = OwningAbility->GetCurrentActorInfo()->PlayerController.Get();
check(PC);
FVector ViewStart;
FRotator ViewRot;
PC->GetPlayerViewPoint(ViewStart, ViewRot);
const FVector ViewDir = ViewRot.Vector();
FVector ViewEnd = ViewStart + (ViewDir * MaxRange);
ClipCameraRayToAbilityRange(ViewStart, ViewDir, TraceStart, MaxRange, ViewEnd);
FHitResult HitResult;
LineTraceWithFilter(HitResult, InSourceActor->GetWorld(), Filter, ViewStart, ViewEnd, TraceProfile.Name, Params);
const bool bUseTraceResult = HitResult.bBlockingHit && (FVector::DistSquared(TraceStart, HitResult.Location) <= (MaxRange * MaxRange));
const FVector AdjustedEnd = (bUseTraceResult) ? HitResult.Location : ViewEnd;
FVector AdjustedAimDir = (AdjustedEnd - TraceStart).GetSafeNormal();
if (AdjustedAimDir.IsZero())
{
AdjustedAimDir = ViewDir;
}
if (!bTraceAffectsAimPitch && bUseTraceResult)
{
FVector OriginalAimDir = (ViewEnd - TraceStart).GetSafeNormal();
if (!OriginalAimDir.IsZero())
{
// Convert to angles and use original pitch
const FRotator OriginalAimRot = OriginalAimDir.Rotation();
FRotator AdjustedAimRot = AdjustedAimDir.Rotation();
AdjustedAimRot.Pitch = OriginalAimRot.Pitch;
AdjustedAimDir = AdjustedAimRot.Vector();
}
}
OutTraceEnd = TraceStart + (AdjustedAimDir * MaxRange);
}
示例3: ExecuteTask
EBTNodeResult::Type URandomWander::ExecuteTask(UBehaviorTreeComponent& OwnerComp, uint8* NodeMemory)
{
UBlackboardComponent* Blackboard = OwnerComp.GetBlackboardComponent();
if (!GetWorld())
{
return EBTNodeResult::Failed;
}
FVector NewWaypoint = FVector::ZeroVector;
FVector CurrentPos = Blackboard->GetOwner()->GetActorLocation();
NewWaypoint.X = CurrentPos.X + FMath::FRandRange(-5000, 5000);
NewWaypoint.Y = CurrentPos.Y + FMath::FRandRange(-5000, 5000);
while (FVector::Dist(NewWaypoint, Blackboard->GetOwner()->GetActorLocation()) <= 2000.f && TraceFromPosition(OutResult, 100.f, ECollisionChannel::ECC_EngineTraceChannel1, NewWaypoint, OwnerComp) == false)
{
NewWaypoint.X = CurrentPos.X + FMath::FRandRange(-5000, 5000);
NewWaypoint.Y = CurrentPos.Y + FMath::FRandRange(-5000, 5000);
}
if (!NewWaypoint.IsZero())
{
Blackboard->SetValue<UBlackboardKeyType_Vector>(BlackboardKey.GetSelectedKeyID(), NewWaypoint);
return EBTNodeResult::Succeeded;
}
return EBTNodeResult::Failed;
}
示例4: UpdateControlRotation
void AAIController::UpdateControlRotation(float DeltaTime, bool bUpdatePawn)
{
// Look toward focus
FVector FocalPoint = GetFocalPoint();
if( !FocalPoint.IsZero() && GetPawn())
{
FVector Direction = FocalPoint - GetPawn()->GetActorLocation();
FRotator NewControlRotation = Direction.Rotation();
// Don't pitch view of walking pawns unless looking at another pawn
if ( GetPawn()->GetMovementComponent() && GetPawn()->GetMovementComponent()->IsMovingOnGround() &&
PathFollowingComponent && (!PathFollowingComponent->GetMoveGoal() || !Cast<APawn>(PathFollowingComponent->GetMoveGoal()) ) )
{
NewControlRotation.Pitch = 0.f;
}
NewControlRotation.Yaw = FRotator::ClampAxis(NewControlRotation.Yaw);
SetControlRotation(NewControlRotation);
APawn* const P = GetPawn();
if (P && bUpdatePawn)
{
P->FaceRotation(NewControlRotation, DeltaTime);
}
}
}
示例5: CalcVectors
/** Utility for calculating drag direction when you click on this widget. */
void HWidgetUtilProxy::CalcVectors(FSceneView* SceneView, const FViewportClick& Click, FVector& LocalManDir, FVector& WorldManDir, float& DragDirX, float& DragDirY)
{
if(Axis == EAxisList::X)
{
WorldManDir = WidgetMatrix.GetScaledAxis( EAxis::X );
LocalManDir = FVector(1,0,0);
}
else if(Axis == EAxisList::Y)
{
WorldManDir = WidgetMatrix.GetScaledAxis( EAxis::Y );
LocalManDir = FVector(0,1,0);
}
else
{
WorldManDir = WidgetMatrix.GetScaledAxis( EAxis::Z );
LocalManDir = FVector(0,0,1);
}
FVector WorldDragDir = WorldManDir;
if(Mode == WMM_Rotate)
{
if( FMath::Abs(Click.GetDirection() | WorldManDir) > KINDA_SMALL_NUMBER ) // If click direction and circle plane are parallel.. can't resolve.
{
// First, find actual position we clicking on the circle in world space.
const FVector ClickPosition = FMath::LinePlaneIntersection( Click.GetOrigin(),
Click.GetOrigin() + Click.GetDirection(),
WidgetMatrix.GetOrigin(),
WorldManDir );
// Then find Radial direction vector (from center to widget to clicked position).
FVector RadialDir = ( ClickPosition - WidgetMatrix.GetOrigin() );
RadialDir.Normalize();
// Then tangent in plane is just the cross product. Should always be unit length again because RadialDir and WorlManDir should be orthogonal.
WorldDragDir = RadialDir ^ WorldManDir;
}
}
// Transform world-space drag dir to screen space.
FVector ScreenDir = SceneView->ViewMatrices.ViewMatrix.TransformVector(WorldDragDir);
ScreenDir.Z = 0.0f;
if( ScreenDir.IsZero() )
{
DragDirX = 0.0f;
DragDirY = 0.0f;
}
else
{
ScreenDir.Normalize();
DragDirX = ScreenDir.X;
DragDirY = ScreenDir.Y;
}
}
示例6: DrawDebugCylinder
void DrawDebugCylinder(const UWorld* InWorld, FVector const& Start, FVector const& End, float Radius, int32 Segments, FColor const& Color, bool bPersistentLines, float LifeTime, uint8 DepthPriority)
{
// no debug line drawing on dedicated server
if (GEngine->GetNetMode(InWorld) != NM_DedicatedServer)
{
// Need at least 4 segments
Segments = FMath::Max(Segments, 4);
// Rotate a point around axis to form cylinder segments
FVector Segment;
FVector P1, P2, P3, P4;
const int32 AngleInc = 360.f / Segments;
int32 Angle = AngleInc;
// Default for Axis is up
FVector Axis = (End - Start).SafeNormal();
if( Axis.IsZero() )
{
Axis = FVector(0.f, 0.f, 1.f);
}
FVector Perpendicular;
FVector Dummy;
Axis.FindBestAxisVectors(Perpendicular, Dummy);
Segment = Perpendicular.RotateAngleAxis(0, Axis) * Radius;
P1 = Segment + Start;
P3 = Segment + End;
// this means foreground lines can't be persistent
ULineBatchComponent* const LineBatcher = GetDebugLineBatcher( InWorld, bPersistentLines, LifeTime, (DepthPriority == SDPG_Foreground) );
if(LineBatcher != NULL)
{
while( Segments-- )
{
Segment = Perpendicular.RotateAngleAxis(Angle, Axis) * Radius;
P2 = Segment + Start;
P4 = Segment + End;
LineBatcher->DrawLine(P2, P4, Color, DepthPriority);
LineBatcher->DrawLine(P1, P2, Color, DepthPriority);
LineBatcher->DrawLine(P3, P4, Color, DepthPriority);
P1 = P2;
P3 = P4;
Angle += AngleInc;
}
}
}
}
示例7: LineOfSightTo
bool AController::LineOfSightTo(const AActor* Other, FVector ViewPoint, bool bAlternateChecks)
{
if( !Other )
{
return false;
}
if ( ViewPoint.IsZero() )
{
AActor* ViewTarg = GetViewTarget();
ViewPoint = ViewTarg->GetActorLocation();
if( ViewTarg == Pawn )
{
ViewPoint.Z += Pawn->BaseEyeHeight; //look from eyes
}
}
static FName NAME_LineOfSight = FName(TEXT("LineOfSight"));
FCollisionQueryParams CollisionParms(NAME_LineOfSight, true, Other);
CollisionParms.AddIgnoredActor(this->GetPawn());
FVector TargetLocation = Other->GetTargetLocation(Pawn);
bool bHit = GetWorld()->LineTraceTest(ViewPoint, TargetLocation, ECC_Visibility, CollisionParms);
if( !bHit )
{
return true;
}
// if other isn't using a cylinder for collision and isn't a Pawn (which already requires an accurate cylinder for AI)
// then don't go any further as it likely will not be tracing to the correct location
if (!Cast<const APawn>(Other) && Cast<UCapsuleComponent>(Other->GetRootComponent()) == NULL)
{
return false;
}
float distSq = (Other->GetActorLocation() - ViewPoint).SizeSquared();
if ( distSq > FARSIGHTTHRESHOLDSQUARED )
{
return false;
}
if ( !Cast<const APawn>(Other) && (distSq > NEARSIGHTTHRESHOLDSQUARED) )
{
return false;
}
float OtherRadius, OtherHeight;
Other->GetSimpleCollisionCylinder(OtherRadius, OtherHeight);
//try viewpoint to head
bHit = GetWorld()->LineTraceTest(ViewPoint, Other->GetActorLocation() + FVector(0.f,0.f,OtherHeight), ECC_Visibility, CollisionParms);
return !bHit;
}
示例8: CombineAdjustments
static FVector CombineAdjustments(FVector CurrentAdjustment, FVector AdjustmentToAdd)
{
// remove the part of the new adjustment that's parallel to the current adjustment
if (CurrentAdjustment.IsZero())
{
return AdjustmentToAdd;
}
FVector Projection = AdjustmentToAdd.ProjectOnTo(CurrentAdjustment);
Projection = Projection.GetClampedToMaxSize(CurrentAdjustment.Size());
FVector OrthogalAdjustmentToAdd = AdjustmentToAdd - Projection;
return CurrentAdjustment + OrthogalAdjustmentToAdd;
}
示例9: GetMovementBaseVelocity
FVector GetMovementBaseVelocity(const UPrimitiveComponent* MovementBase, const FName BoneName)
{
FVector BaseVelocity = FVector::ZeroVector;
if (MovementBaseUtility::IsDynamicBase(MovementBase))
{
if (BoneName != NAME_None)
{
const FBodyInstance* BodyInstance = MovementBase->GetBodyInstance(BoneName);
if (BodyInstance)
{
BaseVelocity = BodyInstance->GetUnrealWorldVelocity();
return BaseVelocity;
}
}
BaseVelocity = MovementBase->GetComponentVelocity();
if (BaseVelocity.IsZero())
{
// Fall back to actor's Root component
const AActor* Owner = MovementBase->GetOwner();
if (Owner)
{
// Component might be moved manually (not by simulated physics or a movement component), see if the root component of the actor has a velocity.
BaseVelocity = MovementBase->GetOwner()->GetVelocity();
}
}
// Fall back to physics velocity.
if (BaseVelocity.IsZero() && MovementBase->GetBodyInstance())
{
BaseVelocity = MovementBase->GetBodyInstance()->GetUnrealWorldVelocity();
}
}
return BaseVelocity;
}
示例10: ConvertPhysicsLinearVelocity
float UTKMathFunctionLibrary::ConvertPhysicsLinearVelocity(FVector Velocity, TEnumAsByte<enum ESpeedUnit> SpeedUnit)
{
if (Velocity.IsZero()) return 0.f;
float unit = 0;
switch (SpeedUnit)
{
case CentimeterPerSecond:
unit = 1;
break;
case FootPerSecond:
unit = 0.03280839895013;
break;
case MeterPerSecond:
unit = 0.01;
break;
case MeterPerMinute:
unit = 0.6;
break;
case KilometerPerSecond:
unit = 0.00001;
case KilometerPerMinute:
unit = 0.0006;
break;
case KilometerPerHour:
unit = 0.036;
break;
case MilePerHour:
unit = 0.02236936292054;
break;
case Knot:
unit = 0.01943844492441;
break;
case Mach:
unit = 0.00002915451895044;
break;
case SpeedOfLight:
unit = 3.335640951982E-11;
break;
case YardPerSecond:
unit = 0.01093613298338;
break;
default:
break;
};
return Velocity.Size() * unit;
}
示例11: DrawAngles
static void DrawAngles(FCanvas* Canvas, int32 XPos, int32 YPos, EAxisList::Type ManipAxis, FWidget::EWidgetMode MoveMode, const FRotator& Rotation, const FVector& Translation)
{
FString OutputString(TEXT(""));
if (MoveMode == FWidget::WM_Rotate && Rotation.IsZero() == false)
{
//Only one value moves at a time
const FVector EulerAngles = Rotation.Euler();
if (ManipAxis == EAxisList::X)
{
OutputString += FString::Printf(TEXT("Roll: %0.2f"), EulerAngles.X);
}
else if (ManipAxis == EAxisList::Y)
{
OutputString += FString::Printf(TEXT("Pitch: %0.2f"), EulerAngles.Y);
}
else if (ManipAxis == EAxisList::Z)
{
OutputString += FString::Printf(TEXT("Yaw: %0.2f"), EulerAngles.Z);
}
}
else if (MoveMode == FWidget::WM_Translate && Translation.IsZero() == false)
{
//Only one value moves at a time
if (ManipAxis == EAxisList::X)
{
OutputString += FString::Printf(TEXT(" %0.2f"), Translation.X);
}
else if (ManipAxis == EAxisList::Y)
{
OutputString += FString::Printf(TEXT(" %0.2f"), Translation.Y);
}
else if (ManipAxis == EAxisList::Z)
{
OutputString += FString::Printf(TEXT(" %0.2f"), Translation.Z);
}
}
if (OutputString.Len() > 0)
{
FCanvasTextItem TextItem( FVector2D(XPos, YPos), FText::FromString( OutputString ), GEngine->GetSmallFont(), FLinearColor::White );
Canvas->DrawItem( TextItem );
}
}
示例12: Activate
bool UAoEHeal::Activate(class AMech_RPGCharacter* target, FVector targetLocation) {
if (!targetLocation.IsZero()) {
FTempAOESettings settings;
settings.affectedTeam = GetAffectedTeam();
settings.healthChange = GetWeaponHealthChange() * healAmount;
settings.owner = owner;
settings.world = owner->GetWorld();
settings.rate = 0.5F;
settings.radius = 700;
settings.location = targetLocation;
settings.damageType = DamageEnums::Blast;
settings.duration = 3.0F;
settings.usesTarget = false;
settings.heals = true;
AAOEHealthChange::CreateAOEHealthChange(settings);
SetOnCooldown(owner->GetWorld());
return true;
}
return false;
}
示例13: LineOfSightTo
bool AAIController::LineOfSightTo(const AActor* Other, FVector ViewPoint, bool bAlternateChecks) const
{
if (Other == nullptr)
{
return false;
}
if (ViewPoint.IsZero())
{
FRotator ViewRotation;
GetActorEyesViewPoint(ViewPoint, ViewRotation);
// if we still don't have a view point we simply fail
if (ViewPoint.IsZero())
{
return false;
}
}
static FName NAME_LineOfSight = FName(TEXT("LineOfSight"));
FVector TargetLocation = Other->GetTargetLocation(GetPawn());
FCollisionQueryParams CollisionParams(NAME_LineOfSight, true, this->GetPawn());
CollisionParams.AddIgnoredActor(Other);
bool bHit = GetWorld()->LineTraceTestByChannel(ViewPoint, TargetLocation, ECC_Visibility, CollisionParams);
if (!bHit)
{
return true;
}
// if other isn't using a cylinder for collision and isn't a Pawn (which already requires an accurate cylinder for AI)
// then don't go any further as it likely will not be tracing to the correct location
const APawn * OtherPawn = Cast<const APawn>(Other);
if (!OtherPawn && Cast<UCapsuleComponent>(Other->GetRootComponent()) == NULL)
{
return false;
}
const FVector OtherActorLocation = Other->GetActorLocation();
const float DistSq = (OtherActorLocation - ViewPoint).SizeSquared();
if (DistSq > FARSIGHTTHRESHOLDSQUARED)
{
return false;
}
if (!OtherPawn && (DistSq > NEARSIGHTTHRESHOLDSQUARED))
{
return false;
}
float OtherRadius, OtherHeight;
Other->GetSimpleCollisionCylinder(OtherRadius, OtherHeight);
if (!bAlternateChecks || !bLOSflag)
{
//try viewpoint to head
bHit = GetWorld()->LineTraceTestByChannel(ViewPoint, OtherActorLocation + FVector(0.f, 0.f, OtherHeight), ECC_Visibility, CollisionParams);
if (!bHit)
{
return true;
}
}
if (!bSkipExtraLOSChecks && (!bAlternateChecks || bLOSflag))
{
// only check sides if width of other is significant compared to distance
if (OtherRadius * OtherRadius / (OtherActorLocation - ViewPoint).SizeSquared() < 0.0001f)
{
return false;
}
//try checking sides - look at dist to four side points, and cull furthest and closest
FVector Points[4];
Points[0] = OtherActorLocation - FVector(OtherRadius, -1 * OtherRadius, 0);
Points[1] = OtherActorLocation + FVector(OtherRadius, OtherRadius, 0);
Points[2] = OtherActorLocation - FVector(OtherRadius, OtherRadius, 0);
Points[3] = OtherActorLocation + FVector(OtherRadius, -1 * OtherRadius, 0);
int32 IndexMin = 0;
int32 IndexMax = 0;
float CurrentMax = (Points[0] - ViewPoint).SizeSquared();
float CurrentMin = CurrentMax;
for (int32 PointIndex = 1; PointIndex<4; PointIndex++)
{
const float NextSize = (Points[PointIndex] - ViewPoint).SizeSquared();
if (NextSize > CurrentMin)
{
CurrentMin = NextSize;
IndexMax = PointIndex;
}
else if (NextSize < CurrentMax)
{
CurrentMax = NextSize;
IndexMin = PointIndex;
}
}
for (int32 PointIndex = 0; PointIndex<4; PointIndex++)
{
if ((PointIndex != IndexMin) && (PointIndex != IndexMax))
{
//.........这里部分代码省略.........
示例14: InputDelta
/**
* @return true if the delta was handled by this editor mode tool.
*/
bool FModeTool_Texture::InputDelta(FEditorViewportClient* InViewportClient,FViewport* InViewport,FVector& InDrag,FRotator& InRot,FVector& InScale)
{
if( InViewportClient->GetCurrentWidgetAxis() == EAxisList::None )
{
return false;
}
// calculate delta drag for this tick for the call to GEditor->polyTexPan below which is using relative (delta) mode
FVector deltaDrag = InDrag;
if (true == InViewportClient->IsPerspective())
{
// perspective viewports pass the absolute drag so subtract the last tick's drag value to get the delta
deltaDrag -= PreviousInputDrag;
}
PreviousInputDrag = InDrag;
if( !deltaDrag.IsZero() )
{
// Ensure each polygon has a unique base point index.
for( FConstLevelIterator Iterator = InViewportClient->GetWorld()->GetLevelIterator(); Iterator; ++Iterator )
{
UModel* Model = (*Iterator)->Model;
for(int32 SurfaceIndex = 0;SurfaceIndex < Model->Surfs.Num();SurfaceIndex++)
{
FBspSurf& Surf = Model->Surfs[SurfaceIndex];
if(Surf.PolyFlags & PF_Selected)
{
const FVector Base = Model->Points[Surf.pBase];
Surf.pBase = Model->Points.Add(Base);
}
}
FMatrix Mat = GLevelEditorModeTools().GetCustomDrawingCoordinateSystem();
FVector UVW = Mat.InverseTransformVector( deltaDrag ); // InverseTransformNormal because Mat is the transform from the surface/widget's coords to world coords
GEditor->polyTexPan( Model, UVW.X, UVW.Y, 0 ); // 0 is relative mode because UVW is made from deltaDrag - the user input since the last tick
}
}
if( !InRot.IsZero() )
{
const FRotationMatrix RotationMatrix( InRot );
// Ensure each polygon has unique texture vector indices.
for ( TSelectedSurfaceIterator<> It(InViewportClient->GetWorld()) ; It ; ++It )
{
FBspSurf* Surf = *It;
UModel* Model = It.GetModel();
FVector TextureU = Model->Vectors[Surf->vTextureU];
FVector TextureV = Model->Vectors[Surf->vTextureV];
TextureU = RotationMatrix.TransformPosition( TextureU );
TextureV = RotationMatrix.TransformPosition( TextureV );
Surf->vTextureU = Model->Vectors.Add(TextureU);
Surf->vTextureV = Model->Vectors.Add(TextureV);
const bool bUpdateTexCoords = true;
const bool bOnlyRefreshSurfaceMaterials = true;
GEditor->polyUpdateMaster(Model, It.GetSurfaceIndex(), bUpdateTexCoords, bOnlyRefreshSurfaceMaterials);
}
}
if( !InScale.IsZero() )
{
float ScaleU = InScale.X / GEditor->GetGridSize();
float ScaleV = InScale.Y / GEditor->GetGridSize();
ScaleU = 1.f - (ScaleU / 100.f);
ScaleV = 1.f - (ScaleV / 100.f);
// Ensure each polygon has unique texture vector indices.
for( FConstLevelIterator Iterator = InViewportClient->GetWorld()->GetLevelIterator(); Iterator; ++Iterator )
{
UModel* Model = (*Iterator)->Model;
for(int32 SurfaceIndex = 0;SurfaceIndex < Model->Surfs.Num();SurfaceIndex++)
{
FBspSurf& Surf = Model->Surfs[SurfaceIndex];
if(Surf.PolyFlags & PF_Selected)
{
const FVector TextureU = Model->Vectors[Surf.vTextureU];
const FVector TextureV = Model->Vectors[Surf.vTextureV];
Surf.vTextureU = Model->Vectors.Add(TextureU);
Surf.vTextureV = Model->Vectors.Add(TextureV);
}
}
GEditor->polyTexScale( Model, ScaleU, 0.f, 0.f, ScaleV, false );
}
}
return true;
}
示例15: ResolvePenetrationImpl
bool UMovementComponent::ResolvePenetrationImpl(const FVector& ProposedAdjustment, const FHitResult& Hit, const FQuat& NewRotationQuat)
{
// SceneComponent can't be in penetration, so this function really only applies to PrimitiveComponent.
const FVector Adjustment = ConstrainDirectionToPlane(ProposedAdjustment);
if (!Adjustment.IsZero() && UpdatedPrimitive)
{
// See if we can fit at the adjusted location without overlapping anything.
AActor* ActorOwner = UpdatedComponent->GetOwner();
if (!ActorOwner)
{
return false;
}
UE_LOG(LogMovement, Verbose, TEXT("ResolvePenetration: %s.%s at location %s inside %s.%s at location %s by %.3f (netmode: %d)"),
*ActorOwner->GetName(),
*UpdatedComponent->GetName(),
*UpdatedComponent->GetComponentLocation().ToString(),
*GetNameSafe(Hit.GetActor()),
*GetNameSafe(Hit.GetComponent()),
Hit.Component.IsValid() ? *Hit.GetComponent()->GetComponentLocation().ToString() : TEXT("<unknown>"),
Hit.PenetrationDepth,
(uint32)GetNetMode());
// We really want to make sure that precision differences or differences between the overlap test and sweep tests don't put us into another overlap,
// so make the overlap test a bit more restrictive.
const float OverlapInflation = CVarPenetrationOverlapCheckInflation.GetValueOnGameThread();
bool bEncroached = OverlapTest(Hit.TraceStart + Adjustment, NewRotationQuat, UpdatedPrimitive->GetCollisionObjectType(), UpdatedPrimitive->GetCollisionShape(OverlapInflation), ActorOwner);
if (!bEncroached)
{
// Move without sweeping.
MoveUpdatedComponent(Adjustment, NewRotationQuat, false, nullptr, ETeleportType::TeleportPhysics);
UE_LOG(LogMovement, Verbose, TEXT("ResolvePenetration: teleport by %s"), *Adjustment.ToString());
return true;
}
else
{
// Disable MOVECOMP_NeverIgnoreBlockingOverlaps if it is enabled, otherwise we wouldn't be able to sweep out of the object to fix the penetration.
TGuardValue<EMoveComponentFlags> ScopedFlagRestore(MoveComponentFlags, EMoveComponentFlags(MoveComponentFlags & (~MOVECOMP_NeverIgnoreBlockingOverlaps)));
// Try sweeping as far as possible...
FHitResult SweepOutHit(1.f);
bool bMoved = MoveUpdatedComponent(Adjustment, NewRotationQuat, true, &SweepOutHit, ETeleportType::TeleportPhysics);
UE_LOG(LogMovement, Verbose, TEXT("ResolvePenetration: sweep by %s (success = %d)"), *Adjustment.ToString(), bMoved);
// Still stuck?
if (!bMoved && SweepOutHit.bStartPenetrating)
{
// Combine two MTD results to get a new direction that gets out of multiple surfaces.
const FVector SecondMTD = GetPenetrationAdjustment(SweepOutHit);
const FVector CombinedMTD = Adjustment + SecondMTD;
if (SecondMTD != Adjustment && !CombinedMTD.IsZero())
{
bMoved = MoveUpdatedComponent(CombinedMTD, NewRotationQuat, true, nullptr, ETeleportType::TeleportPhysics);
UE_LOG(LogMovement, Verbose, TEXT("ResolvePenetration: sweep by %s (MTD combo success = %d)"), *CombinedMTD.ToString(), bMoved);
}
}
// Still stuck?
if (!bMoved)
{
// Try moving the proposed adjustment plus the attempted move direction. This can sometimes get out of penetrations with multiple objects
const FVector MoveDelta = ConstrainDirectionToPlane(Hit.TraceEnd - Hit.TraceStart);
if (!MoveDelta.IsZero())
{
bMoved = MoveUpdatedComponent(Adjustment + MoveDelta, NewRotationQuat, true, nullptr, ETeleportType::TeleportPhysics);
UE_LOG(LogMovement, Verbose, TEXT("ResolvePenetration: sweep by %s (adjusted attempt success = %d)"), *(Adjustment + MoveDelta).ToString(), bMoved);
}
}
return bMoved;
}
}
return false;
}