void URotatingMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) { // skip if we don't want component updated when not rendered or if updated component can't move if (ShouldSkipUpdate(DeltaTime)) { return; } Super::TickComponent(DeltaTime, TickType, ThisTickFunction); if (!IsValid(UpdatedComponent)) { return; } // Compute new rotation const FQuat OldRotation = UpdatedComponent->GetComponentQuat(); const FQuat DeltaRotation = (RotationRate * DeltaTime).Quaternion(); const FQuat NewRotation = bRotationInLocalSpace ? (OldRotation * DeltaRotation) : (DeltaRotation * OldRotation); // Compute new location FVector DeltaLocation = FVector::ZeroVector; if (!PivotTranslation.IsZero()) { const FVector OldPivot = OldRotation.RotateVector(PivotTranslation); const FVector NewPivot = NewRotation.RotateVector(PivotTranslation); DeltaLocation = (OldPivot - NewPivot); // ConstrainDirectionToPlane() not necessary because it's done by MoveUpdatedComponent() below. } const bool bEnableCollision = false; MoveUpdatedComponent(DeltaLocation, NewRotation, bEnableCollision); }
void UCollidingPawnMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction) { Super::TickComponent(DeltaTime, TickType, ThisTickFunction); // some amazing coding here // Make sure that every thing is still valid and we are allowed to move if (!PawnOwner || !UpdatedComponent || ShouldSkipUpdate(DeltaTime)) { return; } // Get (and then clear) the movement vector that we set in ACollidingPawn::Tick FVector DesiredMovementThisFrame = ConsumeInputVector().GetClampedToMaxSize(1.0f)*DeltaTime*150.0f; if (!DesiredMovementThisFrame.IsNearlyZero()) { FHitResult Hit; SafeMoveUpdatedComponent(DesiredMovementThisFrame, UpdatedComponent->GetComponentRotation(), true, Hit); // If we bumped into something, try to slide along it // this check is important because otherwise the pawn will simply stop /* if (Hit.IsValidBlockingHit()) { SlideAlongSurface(DesiredMovementThisFrame, 1.f - Hit.Time, Hit.Normal, Hit); }*/ } }
void UpdateChecker::Run() { // no initialization to do, so signal readiness immediately SignalReady(); try { const std::string url = Settings::GetAppcastURL(); if ( url.empty() ) throw std::runtime_error("Appcast URL not specified."); CheckForInsecureURL(url, "appcast feed"); StringDownloadSink appcast_xml; DownloadFile(url, &appcast_xml, GetAppcastDownloadFlags()); Appcast appcast = Appcast::Load(appcast_xml.data); if (!appcast.ReleaseNotesURL.empty()) CheckForInsecureURL(appcast.ReleaseNotesURL, "release notes"); if (!appcast.DownloadURL.empty()) CheckForInsecureURL(appcast.DownloadURL, "update file"); Settings::WriteConfigValue("LastCheckTime", time(NULL)); const std::string currentVersion = WideToAnsi(Settings::GetAppBuildVersion()); // Check if our version is out of date. if ( !appcast.IsValid() || CompareVersions(currentVersion, appcast.Version) >= 0 ) { // The same or newer version is already installed. UI::NotifyNoUpdates(ShouldAutomaticallyInstall()); return; } // Check if the user opted to ignore this particular version. if ( ShouldSkipUpdate(appcast) ) { UI::NotifyNoUpdates(ShouldAutomaticallyInstall()); return; } UI::NotifyUpdateAvailable(appcast, ShouldAutomaticallyInstall()); } catch ( ... ) { UI::NotifyUpdateError(); throw; } }
void UFloatingPawnMovement::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) { Super::TickComponent(DeltaTime, TickType, ThisTickFunction); if (!PawnOwner || !UpdatedComponent || ShouldSkipUpdate(DeltaTime)) { return; } const AController* Controller = PawnOwner->GetController(); if (Controller && Controller->IsLocalController()) { ApplyControlInputToVelocity(DeltaTime); LimitWorldBounds(); bPositionCorrected = false; // Move actor FVector Delta = Velocity * DeltaTime; if (!Delta.IsNearlyZero(1e-6f)) { const FVector OldLocation = UpdatedComponent->GetComponentLocation(); const FRotator Rotation = UpdatedComponent->GetComponentRotation(); FVector TraceStart = OldLocation; FHitResult Hit(1.f); SafeMoveUpdatedComponent(Delta, Rotation, true, Hit); if (Hit.IsValidBlockingHit()) { HandleImpact(Hit, DeltaTime, Delta); // Try to slide the remaining distance along the surface. SlideAlongSurface(Delta, 1.f-Hit.Time, Hit.Normal, Hit, true); } // Update velocity // We don't want position changes to vastly reverse our direction (which can happen due to penetration fixups etc) if (!bPositionCorrected) { const FVector NewLocation = UpdatedComponent->GetComponentLocation(); Velocity = ((NewLocation - OldLocation) / DeltaTime); } } // Finalize UpdateComponentVelocity(); } };
void UProjectileMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) { QUICK_SCOPE_CYCLE_COUNTER( STAT_ProjectileMovementComponent_TickComponent ); // skip if don't want component updated when not rendered or updated component can't move if (HasStoppedSimulation() || ShouldSkipUpdate(DeltaTime)) { return; } Super::TickComponent(DeltaTime, TickType, ThisTickFunction); AActor* ActorOwner = UpdatedComponent->GetOwner(); if ( !ActorOwner || !CheckStillInWorld() ) { return; } if (UpdatedComponent->IsSimulatingPhysics()) { return; } float RemainingTime = DeltaTime; uint32 NumBounces = 0; int32 Iterations = 0; FHitResult Hit(1.f); while( RemainingTime >= MIN_TICK_TIME && (Iterations < MaxSimulationIterations) && !ActorOwner->IsPendingKill() && !HasStoppedSimulation() ) { Iterations++; // subdivide long ticks to more closely follow parabolic trajectory const float TimeTick = ShouldUseSubStepping() ? GetSimulationTimeStep(RemainingTime, Iterations) : RemainingTime; RemainingTime -= TimeTick; Hit.Time = 1.f; const FVector OldVelocity = Velocity; const FVector MoveDelta = ComputeMoveDelta(OldVelocity, TimeTick); const FRotator NewRotation = (bRotationFollowsVelocity && !OldVelocity.IsNearlyZero(0.01f)) ? OldVelocity.Rotation() : ActorOwner->GetActorRotation(); // Move the component if (bShouldBounce) { // If we can bounce, we are allowed to move out of penetrations, so use SafeMoveUpdatedComponent which does that automatically. SafeMoveUpdatedComponent( MoveDelta, NewRotation, true, Hit ); } else { // If we can't bounce, then we shouldn't adjust if initially penetrating, because that should be a blocking hit that causes a hit event and stop simulation. TGuardValue<EMoveComponentFlags> ScopedFlagRestore(MoveComponentFlags, MoveComponentFlags | MOVECOMP_NeverIgnoreBlockingOverlaps); MoveUpdatedComponent(MoveDelta, NewRotation, true, &Hit ); } // If we hit a trigger that destroyed us, abort. if( ActorOwner->IsPendingKill() || HasStoppedSimulation() ) { return; } // Handle hit result after movement if( !Hit.bBlockingHit ) { PreviousHitTime = 1.f; bIsSliding = false; // Only calculate new velocity if events didn't change it during the movement update. if (Velocity == OldVelocity) { Velocity = ComputeVelocity(Velocity, TimeTick); } } else { // Only calculate new velocity if events didn't change it during the movement update. if (Velocity == OldVelocity) { // re-calculate end velocity for partial time Velocity = (Hit.Time > KINDA_SMALL_NUMBER) ? ComputeVelocity(OldVelocity, TimeTick * Hit.Time) : OldVelocity; } // Handle blocking hit float SubTickTimeRemaining = TimeTick * (1.f - Hit.Time); const EHandleBlockingHitResult HandleBlockingResult = HandleBlockingHit(Hit, TimeTick, MoveDelta, SubTickTimeRemaining); if (HandleBlockingResult == EHandleBlockingHitResult::Abort || HasStoppedSimulation()) { break; } else if (HandleBlockingResult == EHandleBlockingHitResult::Deflect) { NumBounces++; HandleDeflection(Hit, OldVelocity, NumBounces, SubTickTimeRemaining); PreviousHitTime = Hit.Time; PreviousHitNormal = ConstrainNormalToPlane(Hit.Normal); } else if (HandleBlockingResult == EHandleBlockingHitResult::AdvanceNextSubstep) { // Reset deflection logic to ignore this hit PreviousHitTime = 1.f; } else { // Unhandled EHandleBlockingHitResult checkNoEntry(); } // A few initial bounces should add more time and iterations to complete most of the simulation. if (NumBounces <= 2 && SubTickTimeRemaining >= MIN_TICK_TIME) { RemainingTime += SubTickTimeRemaining; Iterations--; } } } UpdateComponentVelocity(); }
void UInterpToMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction) { QUICK_SCOPE_CYCLE_COUNTER(STAT_InterpToMovementComponent_TickComponent); Super::TickComponent(DeltaTime, TickType, ThisTickFunction); // skip if don't want component updated when not rendered or updated component can't move if (!UpdatedComponent || ShouldSkipUpdate(DeltaTime)) { return; } AActor* ActorOwner = UpdatedComponent->GetOwner(); if (!ActorOwner || !CheckStillInWorld()) { return; } if (UpdatedComponent->IsSimulatingPhysics()) { return; } if((bStopped == true ) || ( ActorOwner->IsPendingKill() ) ) { return; } if( ControlPoints.Num()== 0 ) { return; } // This will update any control points coordinates that are linked to actors. UpdateControlPoints(false); float RemainingTime = DeltaTime; int32 NumBounces = 0; int32 Iterations = 0; FHitResult Hit(1.f); FVector WaitPos = FVector::ZeroVector; if (bIsWaiting == true) { WaitPos = UpdatedComponent->GetComponentLocation(); } while (RemainingTime >= MIN_TICK_TIME && (Iterations < MaxSimulationIterations) && !ActorOwner->IsPendingKill() && UpdatedComponent) { Iterations++; const float TimeTick = ShouldUseSubStepping() ? GetSimulationTimeStep(RemainingTime, Iterations) : RemainingTime; RemainingTime -= TimeTick; // Calculate the current time with this tick iteration float Time = FMath::Clamp(CurrentTime + ((DeltaTime*TimeMultiplier)*CurrentDirection),0.0f,1.0f); FVector MoveDelta = ComputeMoveDelta(Time); // Update the rotation on the spline if required FRotator CurrentRotation = UpdatedComponent->GetComponentRotation(); // Move the component if ((bPauseOnImpact == false ) && (BehaviourType != EInterpToBehaviourType::OneShot)) { // If we can bounce, we are allowed to move out of penetrations, so use SafeMoveUpdatedComponent which does that automatically. SafeMoveUpdatedComponent(MoveDelta, CurrentRotation, true, Hit); } else { // If we can't bounce, then we shouldn't adjust if initially penetrating, because that should be a blocking hit that causes a hit event and stop simulation. TGuardValue<EMoveComponentFlags> ScopedFlagRestore(MoveComponentFlags, MoveComponentFlags | MOVECOMP_NeverIgnoreBlockingOverlaps); MoveUpdatedComponent(MoveDelta, CurrentRotation, true, &Hit); } //DrawDebugPoint(GetWorld(), UpdatedComponent->GetComponentLocation(), 16, FColor::White,true,5.0f); // If we hit a trigger that destroyed us, abort. if (ActorOwner->IsPendingKill() || !UpdatedComponent) { return; } // Handle hit result after movement if (!Hit.bBlockingHit) { // If we were 'waiting' were not any more - broadcast we are off again if( bIsWaiting == true ) { OnWaitEndDelegate.Broadcast(Hit, Time); bIsWaiting = false; } else { CalculateNewTime(CurrentTime, TimeTick, Hit, true, bStopped); if (bStopped == true) { return; } } } else { if (HandleHitWall(Hit, TimeTick, MoveDelta)) { break; } NumBounces++; float SubTickTimeRemaining = TimeTick * (1.f - Hit.Time); // A few initial bounces should add more time and iterations to complete most of the simulation. if (NumBounces <= 2 && SubTickTimeRemaining >= MIN_TICK_TIME) { RemainingTime += SubTickTimeRemaining; Iterations--; } } } if( bIsWaiting == false ) { FHitResult DummyHit; CurrentTime = CalculateNewTime(CurrentTime, DeltaTime, DummyHit, false, bStopped); } UpdateComponentVelocity(); }
void UMainCharacterMovementComponent::TickComponent(float deltaTime, enum ELevelTick tickType, FActorComponentTickFunction *thisTickFunction) { UPawnMovementComponent::TickComponent(deltaTime, tickType, thisTickFunction); if (!PawnOwner || !UpdatedComponent || ShouldSkipUpdate(deltaTime)) { return; } if (m_character) { const FVector posInRoom = m_character->GetRelativePositionInRoom(); // pos should be center of room if (auto* room = m_character->GetCurrentRoom()) { int ladderPosInRoom = room->GetLadderPos(); bool isInsideLadderRegion = abs(posInRoom.X - ladderPosInRoom) <= (ARoom::c_ladderWidth * 0.5); // handle climbing up if (isInsideLadderRegion) { if (m_wantsToClimbUp) { if (room->HasLadderUp()) { if (auto* neighbour = room->GetNeighbour(RoomNeighbour::Up)) { m_isMoving = false; m_character->TeleportToRoom(neighbour); } } } // handle climbing down if (m_wantsToClimbDown) { if (room->HasLadderDown()) { if (auto* neighbour = room->GetNeighbour(RoomNeighbour::Down)) { m_isMoving = false; m_character->TeleportToRoom(neighbour); } } } } // handle left and right FVector desiredMovementThisFrame = ConsumeInputVector().GetClampedToMaxSize(1.0f) * deltaTime * m_walkSpeed; if (!desiredMovementThisFrame.IsNearlyZero()) { m_isMoving = true; if (desiredMovementThisFrame.X < 0.0f) { m_direction = FacingDirection::Left; } else if (desiredMovementThisFrame.X > 0.0f) { m_direction = FacingDirection::Right; } const float leftWallPos = room->GetLeftWallXPos(); const float rightWallPos = room->GetRightWallXPos(); FVector desiredPosInRoom = posInRoom - desiredMovementThisFrame; // no neighbour == wall // poor collision detection that won't work in low FPS (but hey, who gives a f***s?) // hint: not me if (!room->GetNeighbour(RoomNeighbour::Left) && desiredMovementThisFrame.X < 0 && desiredPosInRoom.X < leftWallPos) { desiredMovementThisFrame.X = 0; m_isMoving = false; } if (!room->GetNeighbour(RoomNeighbour::Right) && desiredMovementThisFrame.X > 0 && desiredPosInRoom.X > rightWallPos) { desiredMovementThisFrame.X = 0; m_isMoving = false; } FHitResult hit; MoveUpdatedComponent(desiredMovementThisFrame, UpdatedComponent->GetComponentRotation().Quaternion(), true, &hit); } else { m_isMoving = false; } } } m_wantsToClimbUp = false; m_wantsToClimbDown = false; }