void ACSExplosive::Explode_Implementation(ACSCharacterBase* InInstigator) { if (!bExploded) { bExploded = true; const FVector MyLocation = GetActorLocation(); const register float RadiusSq = FMath::Square(ExplodeRadius); for (TActorIterator<ACSCharacterBase> I(GetWorld()); I; ++I) { const FVector OtherLocation = I->GetActorLocation(); FVector Direction = OtherLocation - MyLocation; const register float DistanceSq = Direction.SizeSquared(); if (DistanceSq <= RadiusSq) { const register float Distance = FMath::Sqrt(DistanceSq); Direction /= Distance; const register float Ratio = Distance / ExplodeRadius; const int32 Damage = FMath::RoundToInt(FMath::Lerp((float)CenterDamage, (float)BorderDamage, Ratio)); I->TakeExplosion(this, InInstigator, Direction, Damage, Ratio); } } if (nullptr != ExplodeParticle) { UGameplayStatics::SpawnEmitterAtLocation(GetWorld(), ExplodeParticle, MyLocation)->SetRelativeScale3D(ExplodeParticleScale); } if (nullptr != ExplodeSound) { UGameplayStatics::PlaySoundAtLocation(GetWorld(), ExplodeSound, MyLocation); } Destroy(); for (TActorIterator<ACSExplosive> I(GetWorld()); I; ++I) { if (this != *I && !I->bExploded) { const FVector OtherLocation = I->GetActorLocation(); FVector Direction = OtherLocation - MyLocation; const register float DistanceSq = Direction.SizeSquared(); if (DistanceSq <= RadiusSq) { I->Explode(InInstigator); } } } } }
void ATP_TwinStickPawn::FireShot(FVector FireDirection) { // If we it's ok to fire again if (bCanFire == true) { // If we are pressing fire stick in a direction if (FireDirection.SizeSquared() > 0.0f) { const FRotator FireRotation = FireDirection.Rotation(); // Spawn projectile at an offset from this pawn const FVector SpawnLocation = GetActorLocation() + FireRotation.RotateVector(GunOffset); UWorld* const World = GetWorld(); if (World != NULL) { // spawn the projectile World->SpawnActor<ATP_TwinStickProjectile>(SpawnLocation, FireRotation); } bCanFire = false; World->GetTimerManager().SetTimer(TimerHandle_ShotTimerExpired, this, &ATP_TwinStickPawn::ShotTimerExpired, FireRate); // try and play the sound if specified if (FireSound != nullptr) { UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation()); } bCanFire = false; } } }
void ATP_TwinStickPawn::Tick(float DeltaSeconds) { // Find movement direction const float ForwardValue = GetInputAxisValue(MoveForwardBinding); const float RightValue = GetInputAxisValue(MoveRightBinding); // Clamp max size so that (X=1, Y=1) doesn't cause faster movement in diagonal directions const FVector MoveDirection = FVector(ForwardValue, RightValue, 0.f).GetClampedToMaxSize(1.0f); // Calculate movement const FVector Movement = MoveDirection * MoveSpeed * DeltaSeconds; // If non-zero size, move this actor if (Movement.SizeSquared() > 0.0f) { const FRotator NewRotation = Movement.Rotation(); FHitResult Hit(1.f); RootComponent->MoveComponent(Movement, NewRotation, true, &Hit); if (Hit.IsValidBlockingHit()) { const FVector Normal2D = Hit.Normal.GetSafeNormal2D(); const FVector Deflection = FVector::VectorPlaneProject(Movement, Normal2D) * (1.f - Hit.Time); RootComponent->MoveComponent(Deflection, NewRotation, true); } } // Create fire direction vector const float FireForwardValue = GetInputAxisValue(FireForwardBinding); const float FireRightValue = GetInputAxisValue(FireRightBinding); const FVector FireDirection = FVector(FireForwardValue, FireRightValue, 0.f); // Try and fire a shot FireShot(FireDirection); }
bool FSeparatingAxisPointCheck::FindSeparatingAxisGeneric() { check(PolyVertices.Num() > 3); int32 LastIndex = PolyVertices.Num() - 1; for (int32 Index = 0; Index < PolyVertices.Num(); Index++) { const FVector& V0 = PolyVertices[LastIndex]; const FVector& V1 = PolyVertices[Index]; const FVector EdgeDir = V1 - V0; // Box edges x polygon edge if (!TestSeparatingAxisGeneric(FVector(EdgeDir.Y, -EdgeDir.X, 0.0f)) || !TestSeparatingAxisGeneric(FVector(-EdgeDir.Z, 0.0f, EdgeDir.X)) || !TestSeparatingAxisGeneric(FVector(0.0f, EdgeDir.Z, -EdgeDir.Y))) { return false; } LastIndex = Index; } // Box faces. if (!TestSeparatingAxisGeneric(FVector(0.0f, 0.0f, 1.0f)) || !TestSeparatingAxisGeneric(FVector(1.0f, 0.0f, 0.0f)) || !TestSeparatingAxisGeneric(FVector(0.0f, 1.0f, 0.0f))) { return false; } // Polygon normal. int32 Index0 = PolyVertices.Num() - 2; int32 Index1 = Index0 + 1; for (int32 Index2 = 0; Index2 < PolyVertices.Num(); Index2++) { const FVector& V0 = PolyVertices[Index0]; const FVector& V1 = PolyVertices[Index1]; const FVector& V2 = PolyVertices[Index2]; const FVector EdgeDir0 = V1 - V0; const FVector EdgeDir1 = V2 - V1; FVector Normal = FVector::CrossProduct(EdgeDir1, EdgeDir0); if (Normal.SizeSquared() > SMALL_NUMBER) { if (!TestSeparatingAxisGeneric(Normal)) { return false; } break; } Index0 = Index1; Index1 = Index2; } return true; }
void UCrowdFollowingComponent::UpdateCachedDirections(const FVector& NewVelocity, const FVector& NextPathCorner, bool bTraversingLink) { // MoveSegmentDirection = direction on string pulled path const FVector AgentLoc = GetCrowdAgentLocation(); const FVector ToCorner = NextPathCorner - AgentLoc; if (ToCorner.SizeSquared() > FMath::Square(10.0f)) { MoveSegmentDirection = ToCorner.GetSafeNormal(); } // CrowdAgentMoveDirection either direction on path or aligned with current velocity if (!bTraversingLink) { CrowdAgentMoveDirection = bRotateToVelocity && (NewVelocity.SizeSquared() > KINDA_SMALL_NUMBER) ? NewVelocity.GetSafeNormal() : MoveSegmentDirection; } }
/** * Function for adding a sphere collision primitive to the supplied collision geometry based on a set of Verts. * * Simply put an AABB around mesh and use that to generate centre and radius. * It checks that the AABB is square, and that all vertices are either at the * centre, or within 5% of the radius distance away. */ void AddSphereGeomFromVerts( const TArray<FVector>& Verts, FKAggregateGeom* AggGeom, const TCHAR* ObjName ) { if(Verts.Num() == 0) { return; } FBox Box(0); for(int32 i=0; i<Verts.Num(); i++) { Box += Verts[i]; } FVector Center, Extents; Box.GetCenterAndExtents(Center, Extents); float Longest = 2.f * Extents.GetMax(); float Shortest = 2.f * Extents.GetMin(); // check that the AABB is roughly a square (5% tolerance) if((Longest - Shortest)/Longest > 0.05f) { UE_LOG(LogStaticMeshEdit, Log, TEXT("AddSphereGeomFromVerts (%s): Sphere bounding box not square."), ObjName); return; } float Radius = 0.5f * Longest; // Test that all vertices are a similar radius (5%) from the sphere centre. float MaxR = 0; float MinR = BIG_NUMBER; for(int32 i=0; i<Verts.Num(); i++) { FVector CToV = Verts[i] - Center; float RSqr = CToV.SizeSquared(); MaxR = FMath::Max(RSqr, MaxR); // Sometimes vertex at centre, so reject it. if(RSqr > KINDA_SMALL_NUMBER) { MinR = FMath::Min(RSqr, MinR); } } MaxR = FMath::Sqrt(MaxR); MinR = FMath::Sqrt(MinR); if((MaxR-MinR)/Radius > 0.05f) { UE_LOG(LogStaticMeshEdit, Log, TEXT("AddSphereGeomFromVerts (%s): Vertices not at constant radius."), ObjName ); return; } // Allocate sphere in array FKSphereElem SphereElem; SphereElem.Center = Center; SphereElem.Radius = Radius; AggGeom->SphereElems.Add(SphereElem); }
void CheckVector( FVector ResultVector, FVector ExpectedVector, FString TestName, FString ParameterName, int32 TestIndex, float Tolerance = KINDA_SMALL_NUMBER ) { const FVector Delta = ExpectedVector - ResultVector; if (Delta.SizeSquared() > FMath::Square(Tolerance)) { //UE_LOG(CollisionAutomationTestLog, Log, TEXT("%d:HitResult=(%s)"), iTest+1, *OutHits[iHits].ToString()); TestBase->AddError(FString::Printf(TEXT("Test %d:%s %s mismatch. Should be %s but is actually %s."), TestIndex, *TestName, *ParameterName, *ExpectedVector.ToString(), *ResultVector.ToString())); } }
float AActor::GetNetPriority(const FVector& ViewPos, const FVector& ViewDir, AActor* Viewer, AActor* ViewTarget, UActorChannel* InChannel, float Time, bool bLowBandwidth) { PRAGMA_DISABLE_DEPRECATION_WARNINGS // Call the deprecated version so subclasses will still work for a version float DeprecatedValue = AActor::GetNetPriority(ViewPos, ViewDir, Cast<APlayerController>(Viewer), InChannel, Time, bLowBandwidth); PRAGMA_ENABLE_DEPRECATION_WARNINGS if (DeprecatedValue != DEPRECATED_NET_PRIORITY) { return DeprecatedValue; } if (bNetUseOwnerRelevancy && Owner) { // If we should use our owner's priority, pass it through return Owner->GetNetPriority(ViewPos, ViewDir, Viewer, ViewTarget, InChannel, Time, bLowBandwidth); } if (ViewTarget && (this == ViewTarget || Instigator == ViewTarget)) { // If we're the view target or owned by the view target, use a high priority Time *= 4.f; } else if (!bHidden && GetRootComponent() != NULL) { // If this actor has a location, adjust priority based on location FVector Dir = GetActorLocation() - ViewPos; float DistSq = Dir.SizeSquared(); // Adjust priority based on distance and whether actor is in front of viewer if ((ViewDir | Dir) < 0.f) { if (DistSq > NEARSIGHTTHRESHOLDSQUARED) { Time *= 0.2f; } else if (DistSq > CLOSEPROXIMITYSQUARED) { Time *= 0.4f; } } else if ((DistSq < FARSIGHTTHRESHOLDSQUARED) && (FMath::Square(ViewDir | Dir) > 0.5f * DistSq)) { // Compute the amount of distance along the ViewDir vector. Dir is not normalized // Increase priority if we're being looked directly at Time *= 2.f; } else if (DistSq > MEDSIGHTTHRESHOLDSQUARED) { Time *= 0.4f; } } return NetPriority * Time; }
void AGameplayDebuggerReplicator::SelectTargetToDebug() { #if ENABLED_GAMEPLAY_DEBUGGER APlayerController* MyPC = DebugCameraController.IsValid() ? DebugCameraController.Get() : GetLocalPlayerOwner(); if (MyPC) { float bestAim = 0; FVector CamLocation; FRotator CamRotation; check(MyPC->PlayerCameraManager != nullptr); MyPC->PlayerCameraManager->GetCameraViewPoint(CamLocation, CamRotation); FVector FireDir = CamRotation.Vector(); UWorld* World = MyPC->GetWorld(); check(World); APawn* PossibleTarget = nullptr; for (FConstPawnIterator Iterator = World->GetPawnIterator(); Iterator; ++Iterator) { APawn* NewTarget = *Iterator; if (NewTarget == nullptr || NewTarget == MyPC->GetPawn() || (NewTarget->PlayerState != nullptr && NewTarget->PlayerState->bIsABot == false) || NewTarget->GetActorEnableCollision() == false) { continue; } if (NewTarget != MyPC->GetPawn()) { // look for best controlled pawn target const FVector AimDir = NewTarget->GetActorLocation() - CamLocation; float FireDist = AimDir.SizeSquared(); // only find targets which are < 25000 units away if (FireDist < 625000000.f) { FireDist = FMath::Sqrt(FireDist); float newAim = FVector::DotProduct(FireDir, AimDir); newAim = newAim / FireDist; if (newAim > bestAim) { PossibleTarget = NewTarget; bestAim = newAim; } } } } if (PossibleTarget != nullptr && PossibleTarget != LastSelectedActorToDebug) { ServerSetActorToDebug(Cast<AActor>(PossibleTarget)); } } #endif //ENABLED_GAMEPLAY_DEBUGGER }
FVector UFlareSpacecraftNavigationSystem::GetAngularVelocityToAlignAxis(FVector LocalShipAxis, FVector TargetAxis, FVector TargetAngularVelocity, float DeltaSeconds) const { TArray<UActorComponent*> Engines = Spacecraft->GetComponentsByClass(UFlareEngine::StaticClass()); FVector AngularVelocity = Spacecraft->Airframe->GetPhysicsAngularVelocity(); FVector WorldShipAxis = Spacecraft->Airframe->GetComponentToWorld().GetRotation().RotateVector(LocalShipAxis); WorldShipAxis.Normalize(); TargetAxis.Normalize(); FVector RotationDirection = FVector::CrossProduct(WorldShipAxis, TargetAxis); RotationDirection.Normalize(); float Dot = FVector::DotProduct(WorldShipAxis, TargetAxis); float angle = FMath::RadiansToDegrees(FMath::Acos(Dot)); FVector DeltaVelocity = TargetAngularVelocity - AngularVelocity; FVector DeltaVelocityAxis = DeltaVelocity; DeltaVelocityAxis.Normalize(); float TimeToFinalVelocity; if (FMath::IsNearlyZero(DeltaVelocity.SizeSquared())) { TimeToFinalVelocity = 0; } else { FVector SimpleAcceleration = DeltaVelocityAxis * GetAngularAccelerationRate(); // Scale with damages float DamageRatio = GetTotalMaxTorqueInAxis(Engines, DeltaVelocityAxis, true) / GetTotalMaxTorqueInAxis(Engines, DeltaVelocityAxis, false); FVector DamagedSimpleAcceleration = SimpleAcceleration * DamageRatio; FVector Acceleration = DamagedSimpleAcceleration; float AccelerationInAngleAxis = FMath::Abs(FVector::DotProduct(DamagedSimpleAcceleration, RotationDirection)); TimeToFinalVelocity = (DeltaVelocity.Size() / AccelerationInAngleAxis); } float AngleToStop = (DeltaVelocity.Size() / 2) * (FMath::Max(TimeToFinalVelocity,DeltaSeconds)); FVector RelativeResultSpeed; if (AngleToStop > angle) { RelativeResultSpeed = TargetAngularVelocity; } else { float MaxPreciseSpeed = FMath::Min((angle - AngleToStop) / (DeltaSeconds * 0.75f), GetAngularMaxVelocity()); RelativeResultSpeed = RotationDirection; RelativeResultSpeed *= MaxPreciseSpeed; } return RelativeResultSpeed; }
void AGameJamGameCharacter::UpdateAnimation() { const FVector PlayerVelocity = GetVelocity(); const float PlayerSpeedSqr = PlayerVelocity.SizeSquared(); // Are we moving or standing still? UPaperFlipbook* DesiredAnimation = (PlayerSpeedSqr > 0.0f) ? RunningAnimation : IdleAnimation; if( GetSprite()->GetFlipbook() != DesiredAnimation ) { GetSprite()->SetFlipbook(DesiredAnimation); } }
FVector UKismetMathLibrary::ProjectVectorOnToVector(FVector V, FVector Target) { if (Target.SizeSquared() > SMALL_NUMBER) { return V.ProjectOnTo(Target); } else { FFrame::KismetExecutionMessage(TEXT("Divide by zero: ProjectVectorOnToVector with zero Target vector"), ELogVerbosity::Warning); return FVector::ZeroVector; } }
void UEditorEngine::polyTexPan(UModel *Model,int32 PanU,int32 PanV,int32 Absolute) { for(int32 SurfaceIndex = 0;SurfaceIndex < Model->Surfs.Num();SurfaceIndex++) { const FBspSurf& Surf = Model->Surfs[SurfaceIndex]; if(Surf.PolyFlags & PF_Selected) { if(Absolute) { Model->Points[Surf.pBase] = FVector::ZeroVector; } const FVector TextureU = Model->Vectors[Surf.vTextureU]; const FVector TextureV = Model->Vectors[Surf.vTextureV]; Model->Points[Surf.pBase] += PanU * (TextureU / TextureU.SizeSquared()); Model->Points[Surf.pBase] += PanV * (TextureV / TextureV.SizeSquared()); polyUpdateMaster(Model,SurfaceIndex,1); } } }
void UWorldComposition::EvaluateWorldOriginLocation(const FVector& ViewLocation) { UWorld* OwningWorld = GetWorld(); FVector Location = ViewLocation; if (!bRebaseOriginIn3DSpace) { // Consider only XY plane Location.Z = 0.f; } // Request to shift world in case current view is quite far from current origin if (Location.SizeSquared() > FMath::Square(RebaseOriginDistance)) { OwningWorld->RequestNewWorldOrigin(FIntVector(Location.X, Location.Y, Location.Z) + OwningWorld->OriginLocation); } }
bool AGameplayAbilityTargetActor_Trace::ClipCameraRayToAbilityRange(FVector CameraLocation, FVector CameraDirection, FVector AbilityCenter, float AbilityRange, FVector& ClippedPosition) { FVector CameraToCenter = AbilityCenter - CameraLocation; float DotToCenter = FVector::DotProduct(CameraToCenter, CameraDirection); if (DotToCenter >= 0) //If this fails, we're pointed away from the center, but we might be inside the sphere and able to find a good exit point. { float DistanceSquared = CameraToCenter.SizeSquared() - (DotToCenter * DotToCenter); float RadiusSquared = (AbilityRange * AbilityRange); if (DistanceSquared <= RadiusSquared) { float DistanceFromCamera = FMath::Sqrt(RadiusSquared - DistanceSquared); float DistanceAlongRay = DotToCenter + DistanceFromCamera; //Subtracting instead of adding will get the other intersection point ClippedPosition = CameraLocation + (DistanceAlongRay * CameraDirection); //Cam aim point clipped to range sphere return true; } } return false; }
void SimplifyPointsInner(int Index1, int Index2) { if (Index2 - Index1 < 2) { return; } // Find furthest point from the V1..V2 line const FVector V1(SourcePoints[Index1].X, 0.0f, SourcePoints[Index1].Y); const FVector V2(SourcePoints[Index2].X, 0.0f, SourcePoints[Index2].Y); const FVector V1V2 = V2 - V1; const float LineScale = 1.0f / V1V2.SizeSquared(); float FarthestDistanceSquared = -1.0f; int32 FarthestIndex = INDEX_NONE; for (int32 Index = Index1; Index < Index2; ++Index) { const FVector VTest(SourcePoints[Index].X, 0.0f, SourcePoints[Index].Y); const FVector V1VTest = VTest - V1; const float t = FMath::Clamp(FVector::DotProduct(V1VTest, V1V2) * LineScale, 0.0f, 1.0f); const FVector ClosestPointOnV1V2 = V1 + t * V1V2; const float DistanceToLineSquared = FVector::DistSquared(ClosestPointOnV1V2, VTest); if (DistanceToLineSquared > FarthestDistanceSquared) { FarthestDistanceSquared = DistanceToLineSquared; FarthestIndex = Index; } } if (FarthestDistanceSquared > EpsilonSquared) { // Too far, subdivide further SimplifyPointsInner(Index1, FarthestIndex); SimplifyPointsInner(FarthestIndex, Index2); } else { // The farthest point wasn't too far, so omit all the points in between RemovePoints(Index1, Index2); } }
bool UHUDBlueprintLibrary::IsPointOnScreenWithinDistance(UObject* WorldContextObject, const FVector& InWorldLocation, const float& InMaxDistance) { float MaxDistanceSquared = InMaxDistance * InMaxDistance; UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject); if (!World->IsValidLowLevel()) return false; APlayerController* PlayerController = (WorldContextObject ? UGameplayStatics::GetPlayerController(WorldContextObject, 0) : NULL); const FVector Forward = PlayerController->PlayerCameraManager->GetCameraRotation().Vector(); //const FVector Forward = PlayerCharacter->GetActorForwardVector(); const FVector CameraLocation = PlayerController->PlayerCameraManager->GetCameraLocation(); const FVector Offset = (InWorldLocation - CameraLocation).GetSafeNormal(); const FVector2D ViewportSize = FVector2D(GEngine->GameViewport->Viewport->GetSizeXY()); float DotProduct = FVector::DotProduct(Forward, Offset); bool bLocationIsBehindCamera = (DotProduct < 0); if (bLocationIsBehindCamera) { return false; } FVector2D *ScreenPosition = new FVector2D(); PlayerController->ProjectWorldLocationToScreen(InWorldLocation, *ScreenPosition); // Check to see if it's on screen. If it is, ProjectWorldLocationToScreen is all we need, return it. if (ScreenPosition->X >= 0.f && ScreenPosition->X <= ViewportSize.X && ScreenPosition->Y >= 0.f && ScreenPosition->Y <= ViewportSize.Y) { FVector Delta = InWorldLocation - CameraLocation; float DistanceAwaySquared = Delta.SizeSquared(); if (fabsf(DistanceAwaySquared) <= MaxDistanceSquared) { return true; } } return false; }
void AITP380_RocketThingPawn::FireShot(FVector FireDirection) { // If we it's ok to fire again if (bCanFire == true) { // If we are pressing fire stick in a direction if (FireDirection.SizeSquared() > 0.0f) { curFireDirection = FireDirection; UWorld* const World = GetWorld(); /*for (int k = 0; k < NumFiredAtOnce; k++){ FRotator FireRotation = FireDirection.Rotation(); FRotator randRotation = FRotator(FireRotation.Pitch, FireRotation.Yaw + FMath::RandRange(-90, 90), FireRotation.Roll); // Spawn projectile at an offset from this pawn const FVector SpawnLocation = GetActorLocation() + randRotation.RotateVector(GunOffset); if (World != NULL) { // spawn the projectile AWeaponProjectile* projectile = World->SpawnActor<AWeaponProjectile>(SpawnLocation, randRotation); projectile->targetDirection = FireRotation.Vector(); } //bCanFire = false; // try and play the sound if specified if (FireSound != nullptr) { UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation()); } }*/ FireCluster(); if (FireSound != nullptr) { UGameplayStatics::PlaySoundAtLocation(this, FireSound, GetActorLocation()); } World->GetTimerManager().SetTimer(TimerHandle_ShotTimerExpired, this, &AITP380_RocketThingPawn::ShotTimerExpired, FireRate); bCanFire = false; } } }
void AShipPawn::Tick(float DeltaTime) { Super::Tick(DeltaTime); if (bUseFuel) FuelReserve += FuelRecoveryRate; const FVector MoveDirection = FVector(GetInputAxisValue(MoveForwardBinding), GetInputAxisValue(MoveRightBinding), 0.f).GetClampedToMaxSize(1.0f); const float MoveDirectionSizeSquared = MoveDirection.SizeSquared(); if (MoveDirectionSizeSquared > 0.2f) { MeshComponent->SetRelativeRotation(MoveDirection.Rotation()); auto base_force = 1000 * MeshComponent->GetForwardVector() * MovementSpeed; auto input_thrust = 0.0f; if (bUseSeparateThrusterAxes) { input_thrust = GetInputAxisValue(ForwardThrustBinding); } else { input_thrust = MoveDirectionSizeSquared; } if (bUseFuel) { FuelReserve -= input_thrust * FuelUsageRate; if (FuelReserve < 0) FuelReserve = 0.0f; } if (bUseShipMomentum) { MeshComponent->AddForce(base_force * DeltaTime * MeshComponent->GetMass()); } else { MeshComponent->SetPhysicsLinearVelocity(base_force / 50); } } }
void AKappaPawn::Tick(float DeltaSeconds) { GEngine->AddOnScreenDebugMessage(0, 5.f, FColor::Yellow, FString::FromInt(Score)); // Find movement direction const float ForwardValue = GetInputAxisValue(MoveForwardBinding); const float RightValue = GetInputAxisValue(MoveRightBinding); // Clamp max size so that (X=1, Y=1) doesn't cause faster movement in diagonal directions const FVector MoveDirection = FVector(ForwardValue, RightValue, 0.f).GetClampedToMaxSize(1.0f); // Calculate movement const FVector Movement = MoveDirection * MoveSpeed * DeltaSeconds; // If non-zero size, move this actor if (Movement.SizeSquared() > 0.0f) { const FRotator NewRotation = Movement.Rotation(); FHitResult Hit(1.f); RootComponent->MoveComponent(Movement, NewRotation, true, &Hit); if (Hit.IsValidBlockingHit()) { const FVector Normal2D = Hit.Normal.GetSafeNormal2D(); const FVector Deflection = FVector::VectorPlaneProject(Movement, Normal2D) * (1.f - Hit.Time); RootComponent->MoveComponent(Deflection, NewRotation, true); } } // Create fire direction vector /*const float FireForwardValue = GetInputAxisValue(FireForwardBinding); const float FireRightValue = GetInputAxisValue(FireRightBinding); const FVector FireDirection = FVector(FireForwardValue, FireRightValue, 0.f);*/ FVector WorldPosition, WorldDirection; APlayerController* MyController = Cast<APlayerController>(GetController()); MyController->DeprojectMousePositionToWorld(WorldPosition, WorldDirection); const FVector FireDirection = FVector(WorldDirection.Component(0), WorldDirection.Component(1), 0.f); // Try and fire a shot FireShot(FireDirection); }
void UFloatingPawnMovement::ApplyControlInputToVelocity(float DeltaTime) { const FVector ControlAcceleration = GetPendingInputVector().ClampMaxSize(1.f); const float AnalogInputModifier = (ControlAcceleration.SizeSquared() > 0.f ? ControlAcceleration.Size() : 0.f); const float MaxPawnSpeed = GetMaxSpeed() * AnalogInputModifier; const bool bExceedingMaxSpeed = IsExceedingMaxSpeed(MaxPawnSpeed); if (AnalogInputModifier > 0.f && !bExceedingMaxSpeed) { // Apply change in velocity direction if (Velocity.SizeSquared() > 0.f) { Velocity -= (Velocity - ControlAcceleration * Velocity.Size()) * FMath::Min(DeltaTime * 8.f, 1.f); } } else { // Dampen velocity magnitude based on deceleration. if (Velocity.SizeSquared() > 0.f) { const FVector OldVelocity = Velocity; const float VelSize = FMath::Max(Velocity.Size() - FMath::Abs(Deceleration) * DeltaTime, 0.f); Velocity = Velocity.SafeNormal() * VelSize; // Don't allow braking to lower us below max speed if we started above it. if (bExceedingMaxSpeed && Velocity.SizeSquared() < FMath::Square(MaxPawnSpeed)) { Velocity = OldVelocity.SafeNormal() * MaxPawnSpeed; } } } // Apply acceleration and clamp velocity magnitude. const float NewMaxSpeed = (IsExceedingMaxSpeed(MaxPawnSpeed)) ? Velocity.Size() : MaxPawnSpeed; Velocity += ControlAcceleration * FMath::Abs(Acceleration) * DeltaTime; Velocity = Velocity.ClampMaxSize(NewMaxSpeed); ConsumeInputVector(); }
FTransform FActorPositioning::GetSurfaceAlignedTransform(const FPositioningData& Data) { // Sort out the rotation first, then do the location FQuat RotatorQuat = Data.StartTransform.GetRotation(); if (Data.ActorFactory) { RotatorQuat = Data.ActorFactory->AlignObjectToSurfaceNormal(Data.SurfaceNormal, RotatorQuat); } // Choose the largest location offset of the various options (global viewport settings, collision, factory offset) const float SnapOffsetExtent = GetDefault<ULevelEditorViewportSettings>()->SnapToSurface.SnapOffsetExtent; const float CollisionOffsetExtent = FVector::BoxPushOut(Data.SurfaceNormal, Data.PlacementExtent); FVector LocationOffset = Data.SurfaceNormal * FMath::Max(SnapOffsetExtent, CollisionOffsetExtent); if (Data.ActorFactory && LocationOffset.SizeSquared() < Data.ActorFactory->SpawnPositionOffset.SizeSquared()) { // Rotate the Spawn Position Offset to match our rotation LocationOffset = RotatorQuat.RotateVector(-Data.ActorFactory->SpawnPositionOffset); } return FTransform(Data.bAlignRotation ? RotatorQuat : Data.StartTransform.GetRotation(), Data.SurfaceLocation + LocationOffset); }
bool FSeparatingAxisPointCheck::TestSeparatingAxisCommon(const FVector& Axis, float ProjectedPolyMin, float ProjectedPolyMax) { const float ProjectedCenter = FVector::DotProduct(Axis, BoxCenter); const float ProjectedExtent = FVector::DotProduct(Axis.GetAbs(), BoxExtent); const float ProjectedBoxMin = ProjectedCenter - ProjectedExtent; const float ProjectedBoxMax = ProjectedCenter + ProjectedExtent; if (ProjectedPolyMin > ProjectedBoxMax || ProjectedPolyMax < ProjectedBoxMin) { return false; } if (bCalcLeastPenetration) { const float AxisMagnitudeSqr = Axis.SizeSquared(); if (AxisMagnitudeSqr > (SMALL_NUMBER * SMALL_NUMBER)) { const float InvAxisMagnitude = FMath::InvSqrt(AxisMagnitudeSqr); const float MinPenetrationDist = (ProjectedBoxMax - ProjectedPolyMin) * InvAxisMagnitude; const float MaxPenetrationDist = (ProjectedPolyMax - ProjectedBoxMin) * InvAxisMagnitude; if (MinPenetrationDist < BestDist) { BestDist = MinPenetrationDist; HitNormal = -Axis * InvAxisMagnitude; } if (MaxPenetrationDist < BestDist) { BestDist = MaxPenetrationDist; HitNormal = Axis * InvAxisMagnitude; } } } return true; }
float AActor::GetNetPriority(const FVector& ViewPos, const FVector& ViewDir, APlayerController* Viewer, UActorChannel* InChannel, float Time, bool bLowBandwidth) { if ( bNetUseOwnerRelevancy && Owner) { return Owner->GetNetPriority(ViewPos, ViewDir, Viewer, InChannel, Time, bLowBandwidth); } if ( Instigator && (Instigator == Viewer->GetPawn()) ) { Time *= 4.f; } else if ( !bHidden ) { FVector Dir = GetActorLocation() - ViewPos; float DistSq = Dir.SizeSquared(); // adjust priority based on distance and whether actor is in front of viewer if ( (ViewDir | Dir) < 0.f ) { if ( DistSq > NEARSIGHTTHRESHOLDSQUARED ) { Time *= 0.2f; } else if ( DistSq > CLOSEPROXIMITYSQUARED ) { Time *= 0.4f; } } else if ( DistSq > MEDSIGHTTHRESHOLDSQUARED ) { Time *= 0.4f; } } return NetPriority * Time; }
UPrimitiveComponent* UPhysicsSpringComponent::GetSpringCollision(const FVector& Start, const FVector& End, float& Time) const { UWorld* World = GetWorld(); AActor* IgnoreActor = bIgnoreSelf ? GetOwner() : nullptr; static FName NAME_Spring = FName(TEXT("SpringComponent")); FCollisionQueryParams QueryParams(NAME_Spring, true, IgnoreActor); FHitResult Hit; UPrimitiveComponent* CollidedComponent = nullptr; const FVector Delta = End - Start; const float DeltaSizeSqr = Delta.SizeSquared(); if (DeltaSizeSqr > FMath::Square(SMALL_NUMBER)) { if (bool bBlockingHit = World->SweepSingleByChannel(Hit, Start, End, FQuat::Identity, SpringChannel, FCollisionShape::MakeSphere(SpringRadius), QueryParams)) { CollidedComponent = Hit.GetComponent(); Time = CollidedComponent ? Hit.Time : 1.f; } } return CollidedComponent; }
bool AGameNetworkManager::NetworkVelocityNearZero(FVector InVelocity) const { return InVelocity.SizeSquared() < GetDefault<AGameNetworkManager>(GetClass())->MAXNEARZEROVELOCITYSQUARED; }
void AGameplayDebuggingHUDComponent::DrawEQSData(APlayerController* PC, class UGameplayDebuggingComponent *DebugComponent) { #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) && WITH_EQS PrintString(DefaultContext, TEXT("\n{green}EQS {white}[Use + key to switch query]\n")); if (DebugComponent->EQSLocalData.Num() == 0) { return; } const int32 EQSIndex = DebugComponent->EQSLocalData.Num() > 0 ? FMath::Clamp(DebugComponent->CurrentEQSIndex, 0, DebugComponent->EQSLocalData.Num() - 1) : INDEX_NONE; if (!DebugComponent->EQSLocalData.IsValidIndex(EQSIndex)) { return; } { int32 Index = 0; PrintString(DefaultContext, TEXT("{white}Queries: ")); for (auto CurrentQuery : DebugComponent->EQSLocalData) { if (EQSIndex == Index) { PrintString(DefaultContext, FString::Printf(TEXT("{green}%s, "), *CurrentQuery.Name)); } else { PrintString(DefaultContext, FString::Printf(TEXT("{yellow}%s, "), *CurrentQuery.Name)); } Index++; } PrintString(DefaultContext, TEXT("\n")); } auto& CurrentLocalData = DebugComponent->EQSLocalData[EQSIndex]; /** find and draw item selection */ int32 BestItemIndex = INDEX_NONE; { APlayerController* const MyPC = Cast<APlayerController>(PlayerOwner); FVector CamLocation; FVector FireDir; if (!MyPC->GetSpectatorPawn()) { FRotator CamRotation; MyPC->GetPlayerViewPoint(CamLocation, CamRotation); FireDir = CamRotation.Vector(); } else { FireDir = DefaultContext.Canvas->SceneView->GetViewDirection(); CamLocation = DefaultContext.Canvas->SceneView->ViewMatrices.ViewOrigin; } float bestAim = 0; for (int32 Index = 0; Index < CurrentLocalData.RenderDebugHelpers.Num(); ++Index) { auto& CurrentItem = CurrentLocalData.RenderDebugHelpers[Index]; const FVector AimDir = CurrentItem.Location - CamLocation; float FireDist = AimDir.SizeSquared(); FireDist = FMath::Sqrt(FireDist); float newAim = FireDir | AimDir; newAim = newAim / FireDist; if (newAim > bestAim) { BestItemIndex = Index; bestAim = newAim; } } if (BestItemIndex != INDEX_NONE) { DrawDebugSphere(World, CurrentLocalData.RenderDebugHelpers[BestItemIndex].Location, CurrentLocalData.RenderDebugHelpers[BestItemIndex].Radius, 8, FColor::Red, false); int32 FailedTestIndex = CurrentLocalData.RenderDebugHelpers[BestItemIndex].FailedTestIndex; if (FailedTestIndex != INDEX_NONE) { PrintString(DefaultContext, FString::Printf(TEXT("{red}Selected item failed with test %d: {yellow}%s {LightBlue}(%s)\n") , FailedTestIndex , *CurrentLocalData.Tests[FailedTestIndex].ShortName , *CurrentLocalData.Tests[FailedTestIndex].Detailed )); PrintString(DefaultContext, FString::Printf(TEXT("{white}'%s' with score %3.3f\n\n"), *CurrentLocalData.RenderDebugHelpers[BestItemIndex].AdditionalInformation, CurrentLocalData.RenderDebugHelpers[BestItemIndex].FailedScore)); } } } PrintString(DefaultContext, FString::Printf(TEXT("{white}Timestamp: {yellow}%.3f (%.2fs ago)\n") , CurrentLocalData.Timestamp, PC->GetWorld()->GetTimeSeconds() - CurrentLocalData.Timestamp )); PrintString(DefaultContext, FString::Printf(TEXT("{white}Query ID: {yellow}%d\n") , CurrentLocalData.Id )); PrintString(DefaultContext, FString::Printf(TEXT("{white}Query contains %d options: "), CurrentLocalData.Options.Num())); for (int32 OptionIndex = 0; OptionIndex < CurrentLocalData.Options.Num(); ++OptionIndex) { if (OptionIndex == CurrentLocalData.UsedOption) { PrintString(DefaultContext, FString::Printf(TEXT("{green}%s, "), *CurrentLocalData.Options[OptionIndex])); } else { PrintString(DefaultContext, FString::Printf(TEXT("{yellow}%s, "), *CurrentLocalData.Options[OptionIndex])); } } PrintString(DefaultContext, TEXT("\n")); const float RowHeight = 20.0f; const int32 NumTests = CurrentLocalData.Tests.Num(); if (CurrentLocalData.NumValidItems > 0 && GetDebuggingReplicator()->EnableEQSOnHUD ) { // draw test weights for best X items const int32 NumItems = CurrentLocalData.Items.Num(); FCanvasTileItem TileItem(FVector2D(0, 0), GWhiteTexture, FVector2D(Canvas->SizeX, RowHeight), FLinearColor::Black); FLinearColor ColorOdd(0, 0, 0, 0.6f); FLinearColor ColorEven(0, 0, 0.4f, 0.4f); TileItem.BlendMode = SE_BLEND_Translucent; // table header { DefaultContext.CursorY += RowHeight; const float HeaderY = DefaultContext.CursorY + 3.0f; TileItem.SetColor(ColorOdd); DrawItem(DefaultContext, TileItem, 0, DefaultContext.CursorY); float HeaderX = DefaultContext.CursorX; PrintString(DefaultContext, FColor::Yellow, FString::Printf(TEXT("Num items: %d"), CurrentLocalData.NumValidItems), HeaderX, HeaderY); HeaderX += ItemDescriptionWidth; PrintString(DefaultContext, FColor::White, TEXT("Score"), HeaderX, HeaderY); HeaderX += ItemScoreWidth; for (int32 TestIdx = 0; TestIdx < NumTests; TestIdx++) { PrintString(DefaultContext, FColor::White, FString::Printf(TEXT("Test %d"), TestIdx), HeaderX, HeaderY); HeaderX += TestScoreWidth; } DefaultContext.CursorY += RowHeight; } // valid items for (int32 Idx = 0; Idx < NumItems; Idx++) { TileItem.SetColor((Idx % 2) ? ColorOdd : ColorEven); DrawItem(DefaultContext, TileItem, 0, DefaultContext.CursorY); DrawEQSItemDetails(Idx, DebugComponent); DefaultContext.CursorY += RowHeight; } DefaultContext.CursorY += RowHeight; } // test description PrintString(DefaultContext, TEXT("All tests from used option:\n")); for (int32 TestIdx = 0; TestIdx < NumTests; TestIdx++) { FString TestDesc = FString::Printf(TEXT("{white}Test %d = {yellow}%s {LightBlue}(%s)\n"), TestIdx, *CurrentLocalData.Tests[TestIdx].ShortName, *CurrentLocalData.Tests[TestIdx].Detailed); PrintString(DefaultContext, TestDesc); } #endif //!(UE_BUILD_SHIPPING || UE_BUILD_TEST) }
bool UPrimitiveComponent::ApplyRigidBodyState(const FRigidBodyState& NewState, const FRigidBodyErrorCorrection& ErrorCorrection, FVector& OutDeltaPos, FName BoneName) { bool bRestoredState = true; FBodyInstance* BI = GetBodyInstance(BoneName); if (BI && BI->IsInstanceSimulatingPhysics()) { // failure cases const float QuatSizeSqr = NewState.Quaternion.SizeSquared(); if (QuatSizeSqr < KINDA_SMALL_NUMBER) { UE_LOG(LogPhysics, Warning, TEXT("Invalid zero quaternion set for body. (%s:%s)"), *GetName(), *BoneName.ToString()); return bRestoredState; } else if (FMath::Abs(QuatSizeSqr - 1.f) > KINDA_SMALL_NUMBER) { UE_LOG(LogPhysics, Warning, TEXT("Quaternion (%f %f %f %f) with non-unit magnitude detected. (%s:%s)"), NewState.Quaternion.X, NewState.Quaternion.Y, NewState.Quaternion.Z, NewState.Quaternion.W, *GetName(), *BoneName.ToString() ); return bRestoredState; } FRigidBodyState CurrentState; GetRigidBodyState(CurrentState, BoneName); const bool bShouldSleep = (NewState.Flags & ERigidBodyFlags::Sleeping) != 0; /////// POSITION CORRECTION /////// // Find out how much of a correction we are making const FVector DeltaPos = NewState.Position - CurrentState.Position; const float DeltaMagSq = DeltaPos.SizeSquared(); const float BodyLinearSpeedSq = CurrentState.LinVel.SizeSquared(); // Snap position by default (big correction, or we are moving too slowly) FVector UpdatedPos = NewState.Position; FVector FixLinVel = FVector::ZeroVector; // If its a small correction and velocity is above threshold, only make a partial correction, // and calculate a velocity that would fix it over 'fixTime'. if (DeltaMagSq < ErrorCorrection.LinearDeltaThresholdSq && BodyLinearSpeedSq >= ErrorCorrection.BodySpeedThresholdSq) { UpdatedPos = FMath::Lerp(CurrentState.Position, NewState.Position, ErrorCorrection.LinearInterpAlpha); FixLinVel = (NewState.Position - UpdatedPos) * ErrorCorrection.LinearRecipFixTime; } // Get the linear correction OutDeltaPos = UpdatedPos - CurrentState.Position; /////// ORIENTATION CORRECTION /////// // Get quaternion that takes us from old to new const FQuat InvCurrentQuat = CurrentState.Quaternion.Inverse(); const FQuat DeltaQuat = NewState.Quaternion * InvCurrentQuat; FVector DeltaAxis; float DeltaAng; // radians DeltaQuat.ToAxisAndAngle(DeltaAxis, DeltaAng); DeltaAng = FMath::UnwindRadians(DeltaAng); // Snap rotation by default (big correction, or we are moving too slowly) FQuat UpdatedQuat = NewState.Quaternion; FVector FixAngVel = FVector::ZeroVector; // degrees per second // If the error is small, and we are moving, try to move smoothly to it if (FMath::Abs(DeltaAng) < ErrorCorrection.AngularDeltaThreshold ) { UpdatedQuat = FMath::Lerp(CurrentState.Quaternion, NewState.Quaternion, ErrorCorrection.AngularInterpAlpha); FixAngVel = DeltaAxis.GetSafeNormal() * FMath::RadiansToDegrees(DeltaAng) * (1.f - ErrorCorrection.AngularInterpAlpha) * ErrorCorrection.AngularRecipFixTime; } /////// BODY UPDATE /////// BI->SetBodyTransform(FTransform(UpdatedQuat, UpdatedPos), true); BI->SetLinearVelocity(NewState.LinVel + FixLinVel, false); BI->SetAngularVelocity(NewState.AngVel + FixAngVel, false); // state is restored when no velocity corrections are required bRestoredState = (FixLinVel.SizeSquared() < KINDA_SMALL_NUMBER) && (FixAngVel.SizeSquared() < KINDA_SMALL_NUMBER); /////// SLEEP UPDATE /////// const bool bIsAwake = BI->IsInstanceAwake(); if (bIsAwake && (bShouldSleep && bRestoredState)) { BI->PutInstanceToSleep(); } else if (!bIsAwake) { BI->WakeInstance(); } } return bRestoredState; }
void UGripMotionControllerComponent::TickGrip() { if (GrippedActors.Num()) { FTransform WorldTransform; FTransform InverseTransform = this->GetComponentTransform().Inverse(); for (int i = GrippedActors.Num() - 1; i >= 0; --i) { if (GrippedActors[i].Actor || GrippedActors[i].Component) { // GetRelativeTransformReverse had some serious f*****g floating point errors associated with it that was f*****g everything up // Not sure whats wrong with the function but I might want to push a patch out eventually WorldTransform = GrippedActors[i].RelativeTransform.GetRelativeTransform(InverseTransform); UPrimitiveComponent *root = GrippedActors[i].Component; AActor *actor = GrippedActors[i].Actor; if (!root) root = Cast<UPrimitiveComponent>(GrippedActors[i].Actor->GetRootComponent()); if (!root) continue; if (!actor) actor = root->GetOwner(); if (!actor) continue; if (bIsServer) { // Handle collision intersection detection, this is used to intelligently manage some of the networking and late update features. switch (GrippedActors[i].GripCollisionType.GetValue()) { case EGripCollisionType::InteractiveCollisionWithPhysics: case EGripCollisionType::InteractiveHybridCollisionWithSweep: { TArray<FOverlapResult> Hits; FComponentQueryParams Params(NAME_None, this->GetOwner()); Params.bTraceAsyncScene = root->bCheckAsyncSceneOnMove; Params.AddIgnoredActor(actor); Params.AddIgnoredActors(root->MoveIgnoreActors); if(GetWorld()->ComponentOverlapMulti(Hits, root, root->GetComponentLocation(), root->GetComponentQuat(), Params)) { GrippedActors[i].bColliding = true; } else { GrippedActors[i].bColliding = false; } } // Skip collision intersects with these types, they dont need it case EGripCollisionType::PhysicsOnly: case EGripCollisionType::SweepWithPhysics: case EGripCollisionType::InteractiveCollisionWithSweep: default:break; } } // Need to figure out best default behavior /*if (GrippedActors[i].bHasSecondaryAttachment && GrippedActors[i].SecondaryAttachment) { WorldTransform.SetRotation((WorldTransform.GetLocation() - GrippedActors[i].SecondaryAttachment->GetComponentLocation()).ToOrientationRotator().Quaternion()); }*/ if (GrippedActors[i].GripCollisionType == EGripCollisionType::InteractiveCollisionWithPhysics) { UpdatePhysicsHandleTransform(GrippedActors[i], WorldTransform); } else if (GrippedActors[i].GripCollisionType == EGripCollisionType::InteractiveCollisionWithSweep) { if (bIsServer) { FHitResult OutHit; // Need to use without teleport so that the physics velocity is updated for when the actor is released to throw root->SetWorldTransform(WorldTransform, true, &OutHit); if (OutHit.bBlockingHit) { GrippedActors[i].bColliding = true; if (!actor->bReplicateMovement) actor->SetReplicateMovement(true); } else { GrippedActors[i].bColliding = false; if (actor->bReplicateMovement) actor->SetReplicateMovement(false); } } else { if (!GrippedActors[i].bColliding) { root->SetWorldTransform(WorldTransform, true); } } } else if (GrippedActors[i].GripCollisionType == EGripCollisionType::InteractiveHybridCollisionWithSweep) { // Need to use without teleport so that the physics velocity is updated for when the actor is released to throw //if (bIsServer) //{ FBPActorPhysicsHandleInformation * GripHandle = GetPhysicsGrip(GrippedActors[i]); if (!GrippedActors[i].bColliding) { // Make sure that there is no collision on course before turning off collision and snapping to controller if (bIsServer && actor && actor->bReplicateMovement) { FCollisionQueryParams QueryParams(NAME_None, false, this->GetOwner()); FCollisionResponseParams ResponseParam; root->InitSweepCollisionParams(QueryParams, ResponseParam); QueryParams.AddIgnoredActor(actor); QueryParams.AddIgnoredActors(root->MoveIgnoreActors); if (GetWorld()->SweepTestByChannel(root->GetComponentLocation(), WorldTransform.GetLocation(), root->GetComponentQuat(), ECollisionChannel::ECC_Visibility, root->GetCollisionShape(), QueryParams, ResponseParam)) { GrippedActors[i].bColliding = true; } else { GrippedActors[i].bColliding = false; } } // If still not colliding if (!GrippedActors[i].bColliding) { if (bIsServer && actor->bReplicateMovement) // So we don't call on on change event over and over locally actor->SetReplicateMovement(false); if (bIsServer && GripHandle) { DestroyPhysicsHandle(GrippedActors[i]); if(GrippedActors[i].Actor) GrippedActors[i].Actor->DisableComponentsSimulatePhysics(); else root->SetSimulatePhysics(false); } root->SetWorldTransform(WorldTransform, false); } else { if (bIsServer && GrippedActors[i].bColliding && GripHandle) UpdatePhysicsHandleTransform(GrippedActors[i], WorldTransform); } } else if (GrippedActors[i].bColliding && !GripHandle) { if (bIsServer && !actor->bReplicateMovement) actor->SetReplicateMovement(true); root->SetSimulatePhysics(true); if (bIsServer) SetUpPhysicsHandle(GrippedActors[i]); } else { if (bIsServer && GrippedActors[i].bColliding && GripHandle) UpdatePhysicsHandleTransform(GrippedActors[i], WorldTransform); } } else if (GrippedActors[i].GripCollisionType == EGripCollisionType::SweepWithPhysics) { if (bIsServer) { FVector OriginalPosition(root->GetComponentLocation()); FRotator OriginalOrientation(root->GetComponentRotation()); FVector NewPosition(WorldTransform.GetTranslation()); FRotator NewOrientation(WorldTransform.GetRotation()); // Now sweep collision separately so we can get hits but not have the location altered if (bUseWithoutTracking || NewPosition != OriginalPosition || NewOrientation != OriginalOrientation) { FVector move = NewPosition - OriginalPosition; // ComponentSweepMulti does nothing if moving < KINDA_SMALL_NUMBER in distance, so it's important to not try to sweep distances smaller than that. const float MinMovementDistSq = (FMath::Square(4.f*KINDA_SMALL_NUMBER)); if (bUseWithoutTracking || move.SizeSquared() > MinMovementDistSq || NewOrientation != OriginalOrientation) { if (CheckComponentWithSweep(root, move, NewOrientation, false)) { } } } // Move the actor, we are not offsetting by the hit result anyway root->SetWorldTransform(WorldTransform, false); } else { // Move the actor, we are not offsetting by the hit result anyway root->SetWorldTransform(WorldTransform, false); } } else if (GrippedActors[i].GripCollisionType == EGripCollisionType::PhysicsOnly) { // Move the actor, we are not offsetting by the hit result anyway root->SetWorldTransform(WorldTransform, false); } } else { if (bIsServer) { DestroyPhysicsHandle(GrippedActors[i]); GrippedActors.RemoveAt(i); // If it got garbage collected then just remove the pointer, won't happen with new uproperty use, but keeping it here anyway } } } } }
float UKismetMathLibrary::VSizeSquared(FVector A) { return A.SizeSquared(); }