void ACharacter::OnRep_ReplicatedBasedMovement() { if (Role != ROLE_SimulatedProxy) { return; } // Skip base updates while playing root motion, it is handled inside of OnRep_RootMotion if (IsPlayingNetworkedRootMotionMontage()) { return; } TGuardValue<bool> bInBaseReplicationGuard(bInBaseReplication, true); const bool bBaseChanged = (BasedMovement.MovementBase != ReplicatedBasedMovement.MovementBase || BasedMovement.BoneName != ReplicatedBasedMovement.BoneName); if (bBaseChanged) { // Even though we will copy the replicated based movement info, we need to use SetBase() to set up tick dependencies and trigger notifications. SetBase(ReplicatedBasedMovement.MovementBase, ReplicatedBasedMovement.BoneName); } // Make sure to use the values of relative location/rotation etc from the server. BasedMovement = ReplicatedBasedMovement; if (ReplicatedBasedMovement.HasRelativeLocation()) { // Update transform relative to movement base const FVector OldLocation = GetActorLocation(); const FQuat OldRotation = GetActorQuat(); MovementBaseUtility::GetMovementBaseTransform(ReplicatedBasedMovement.MovementBase, ReplicatedBasedMovement.BoneName, CharacterMovement->OldBaseLocation, CharacterMovement->OldBaseQuat); const FVector NewLocation = CharacterMovement->OldBaseLocation + ReplicatedBasedMovement.Location; if (ReplicatedBasedMovement.HasRelativeRotation()) { // Relative location, relative rotation FRotator NewRotation = (FRotationMatrix(ReplicatedBasedMovement.Rotation) * FQuatRotationMatrix(CharacterMovement->OldBaseQuat)).Rotator(); // TODO: need a better way to not assume we only use Yaw. NewRotation.Pitch = 0.f; NewRotation.Roll = 0.f; SetActorLocationAndRotation(NewLocation, NewRotation); } else { // Relative location, absolute rotation SetActorLocationAndRotation(NewLocation, ReplicatedBasedMovement.Rotation); } // When position or base changes, movement mode will need to be updated. This assumes rotation changes don't affect that. CharacterMovement->bJustTeleported |= (bBaseChanged || GetActorLocation() != OldLocation); INetworkPredictionInterface* PredictionInterface = Cast<INetworkPredictionInterface>(GetMovementComponent()); if (PredictionInterface) { PredictionInterface->SmoothCorrection(OldLocation, OldRotation); } } }
void ACharacter::UpdateSimulatedPosition(const FVector& NewLocation, const FRotator& NewRotation) { // Always consider Location as changed if we were spawned this tick as in that case our replicated Location was set as part of spawning, before PreNetReceive() if( (NewLocation != GetActorLocation()) || (CreationTime == GetWorld()->TimeSeconds) ) { FVector FinalLocation = NewLocation; // Only need to check for encroachment when teleported without any velocity. // Normal movement pops the character out of geometry anyway, no use doing it before and after (with different rules). bSimGravityDisabled = false; if (CharacterMovement->Velocity.IsZero()) { if (GetWorld()->EncroachingBlockingGeometry(this, NewLocation, NewRotation)) { bSimGravityDisabled = true; } } // Don't use TeleportTo(), that clears our base. SetActorLocationAndRotation(FinalLocation, NewRotation, false); CharacterMovement->bJustTeleported = true; } else if( NewRotation != GetActorRotation() ) { GetRootComponent()->MoveComponent(FVector::ZeroVector, NewRotation, false); } }
void ACharacter::UpdateSimulatedPosition(const FVector & NewLocation, const FRotator & NewRotation) { // Always consider Location as changed if we were spawned this tick as in that case our replicated Location was set as part of spawning, before PreNetReceive() if( (NewLocation != GetActorLocation()) || (CreationTime == GetWorld()->TimeSeconds) ) { FVector FinalLocation = NewLocation; if( GetWorld()->EncroachingBlockingGeometry(this, NewLocation, NewRotation) ) { bSimGravityDisabled = true; } else { // Correction to make sure pawn doesn't penetrate floor after replication rounding FinalLocation.Z += 0.01f; bSimGravityDisabled = false; } // Don't use TeleportTo(), that clears our base. SetActorLocationAndRotation(FinalLocation, NewRotation, false); } else if( NewRotation != GetActorRotation() ) { GetRootComponent()->MoveComponent(FVector::ZeroVector, NewRotation, false); } }
void AActor::PostNetReceiveLocationAndRotation() { if( RootComponent && RootComponent->IsRegistered() && (ReplicatedMovement.Location != GetActorLocation() || ReplicatedMovement.Rotation != GetActorRotation()) ) { SetActorLocationAndRotation(ReplicatedMovement.Location, ReplicatedMovement.Rotation, /*bSweep=*/ false); } }
void ACharacter::PostNetReceiveBase() { const bool bBaseChanged = (RelativeMovement.MovementBase != MovementBase); if (bBaseChanged) { SetBase(RelativeMovement.MovementBase); } if (RelativeMovement.HasRelativePosition()) { if (bBaseChanged || (RelativeMovement.Location != SavedRelativeLocation) || (RelativeMovement.Rotation != SavedRelativeRotation)) { const FVector OldLocation = GetActorLocation(); const FRotator NewRotation = (FRotationMatrix(RelativeMovement.Rotation) * FRotationMatrix(MovementBase->GetComponentRotation())).Rotator(); SetActorLocationAndRotation( MovementBase->GetComponentLocation() + RelativeMovement.Location, NewRotation, false); INetworkPredictionInterface* PredictionInterface = InterfaceCast<INetworkPredictionInterface>(GetMovementComponent()); if (PredictionInterface) { PredictionInterface->SmoothCorrection(OldLocation); } } } if ( CharacterMovement ) { CharacterMovement->bJustTeleported = false; } }
void ABrush::InitPosRotScale() { check(BrushComponent); SetActorLocationAndRotation(FVector::ZeroVector, FQuat::Identity, false); SetPivotOffset( FVector::ZeroVector ); }
void AMagicBattleSoccerBall::MoveWithPossessor() { // This is used to roll the ball while a possessor owns it. The angle is a function of how far the ball has travelled. NegDistanceTravelled += Possessor->GetVelocity().Size() * -0.015f; // All platforms should move the same way if there is a possessor. SetActorLocationAndRotation(Possessor->GetActorLocation() + Possessor->GetActorForwardVector() * DISTANCE_IN_FRONT_OF_POSSESSOR + FVector(0.0f, 0.0f, POSSESSOR_Z_OFFSET), FRotator(NegDistanceTravelled, Possessor->GetActorRotation().Yaw, 0.0f)); }
void AGameplayAbilityTargetActor_Trace::Tick(float DeltaSeconds) { // very temp - do a mostly hardcoded trace from the source actor if (SourceActor) { FHitResult HitResult = PerformTrace(SourceActor); FVector EndPoint = HitResult.Component.IsValid() ? HitResult.ImpactPoint : HitResult.TraceEnd; if (bDebug) { DrawDebugLine(GetWorld(), SourceActor->GetActorLocation(), EndPoint, FColor::Green, false); DrawDebugSphere(GetWorld(), EndPoint, 16, 10, FColor::Green, false); } SetActorLocationAndRotation(EndPoint, SourceActor->GetActorRotation()); } }
void ABrush::CopyPosRotScaleFrom( ABrush* Other ) { check(BrushComponent); check(Other); check(Other->BrushComponent); SetActorLocationAndRotation(Other->GetActorLocation(), Other->GetActorRotation(), false); if( GetRootComponent() != NULL ) { SetPivotOffset(Other->GetPivotOffset()); } if(Brush) { Brush->BuildBound(); } ReregisterAllComponents(); }
void APawn::PostNetReceiveLocationAndRotation() { // always consider Location as changed if we were spawned this tick as in that case our replicated Location was set as part of spawning, before PreNetReceive() if( (ReplicatedMovement.Location == GetActorLocation() && ReplicatedMovement.Rotation == GetActorRotation()) && (CreationTime != GetWorld()->TimeSeconds) ) { return; } if( Role == ROLE_SimulatedProxy ) { // Correction to make sure pawn doesn't penetrate floor after replication rounding ReplicatedMovement.Location.Z += 0.01f; const FVector OldLocation = GetActorLocation(); const FQuat OldRotation = GetActorQuat(); SetActorLocationAndRotation(ReplicatedMovement.Location, ReplicatedMovement.Rotation, /*bSweep=*/ false); INetworkPredictionInterface* PredictionInterface = Cast<INetworkPredictionInterface>(GetMovementComponent()); if (PredictionInterface) { PredictionInterface->SmoothCorrection(OldLocation, OldRotation, ReplicatedMovement.Location, ReplicatedMovement.Rotation.Quaternion()); } } }
void APlayerCameraManager::UpdateViewTarget(FTViewTarget& OutVT, float DeltaTime) { // Don't update outgoing viewtarget during an interpolation if ((PendingViewTarget.Target != NULL) && BlendParams.bLockOutgoing && OutVT.Equal(ViewTarget)) { return; } // store previous POV, in case we need it later FMinimalViewInfo OrigPOV = OutVT.POV; //@TODO: CAMERA: Should probably reset the view target POV fully here OutVT.POV.FOV = DefaultFOV; OutVT.POV.OrthoWidth = DefaultOrthoWidth; OutVT.POV.bConstrainAspectRatio = false; OutVT.POV.bUseFieldOfViewForLOD = true; OutVT.POV.ProjectionMode = bIsOrthographic ? ECameraProjectionMode::Orthographic : ECameraProjectionMode::Perspective; OutVT.POV.PostProcessSettings.SetBaseValues(); OutVT.POV.PostProcessBlendWeight = 1.0f; bool bDoNotApplyModifiers = false; if (ACameraActor* CamActor = Cast<ACameraActor>(OutVT.Target)) { // Viewing through a camera actor. CamActor->GetCameraComponent()->GetCameraView(DeltaTime, OutVT.POV); } else { static const FName NAME_Fixed = FName(TEXT("Fixed")); static const FName NAME_ThirdPerson = FName(TEXT("ThirdPerson")); static const FName NAME_FreeCam = FName(TEXT("FreeCam")); static const FName NAME_FreeCam_Default = FName(TEXT("FreeCam_Default")); static const FName NAME_FirstPerson = FName(TEXT("FirstPerson")); if (CameraStyle == NAME_Fixed) { // do not update, keep previous camera position by restoring // saved POV, in case CalcCamera changes it but still returns false OutVT.POV = OrigPOV; // don't apply modifiers when using this debug camera mode bDoNotApplyModifiers = true; } else if (CameraStyle == NAME_ThirdPerson || CameraStyle == NAME_FreeCam || CameraStyle == NAME_FreeCam_Default) { // Simple third person view implementation FVector Loc = OutVT.Target->GetActorLocation(); FRotator Rotator = OutVT.Target->GetActorRotation(); if (OutVT.Target == PCOwner) { Loc = PCOwner->GetFocalLocation(); } // Take into account Mesh Translation so it takes into account the PostProcessing we do there. // @fixme, can crash in certain BP cases where default mesh is null // APawn* TPawn = Cast<APawn>(OutVT.Target); // if ((TPawn != NULL) && (TPawn->Mesh != NULL)) // { // Loc += FQuatRotationMatrix(OutVT.Target->GetActorQuat()).TransformVector(TPawn->Mesh->RelativeLocation - GetDefault<APawn>(TPawn->GetClass())->Mesh->RelativeLocation); // } //OutVT.Target.GetActorEyesViewPoint(Loc, Rot); if( CameraStyle == NAME_FreeCam || CameraStyle == NAME_FreeCam_Default ) { Rotator = PCOwner->GetControlRotation(); } FVector Pos = Loc + FRotationMatrix(Rotator).TransformVector(FreeCamOffset) - Rotator.Vector() * FreeCamDistance; FCollisionQueryParams BoxParams(NAME_FreeCam, false, this); BoxParams.AddIgnoredActor(OutVT.Target); FHitResult Result; GetWorld()->SweepSingleByChannel(Result, Loc, Pos, FQuat::Identity, ECC_Camera, FCollisionShape::MakeBox(FVector(12.f)), BoxParams); OutVT.POV.Location = !Result.bBlockingHit ? Pos : Result.Location; OutVT.POV.Rotation = Rotator; // don't apply modifiers when using this debug camera mode bDoNotApplyModifiers = true; } else if (CameraStyle == NAME_FirstPerson) { // Simple first person, view through viewtarget's 'eyes' OutVT.Target->GetActorEyesViewPoint(OutVT.POV.Location, OutVT.POV.Rotation); // don't apply modifiers when using this debug camera mode bDoNotApplyModifiers = true; } else { UpdateViewTargetInternal(OutVT, DeltaTime); } } if (!bDoNotApplyModifiers || bAlwaysApplyModifiers) { // Apply camera modifiers at the end (view shakes for example) ApplyCameraModifiers(DeltaTime, OutVT.POV); } if (bFollowHmdOrientation) { if (GEngine->HMDDevice.IsValid() && GEngine->HMDDevice->IsHeadTrackingAllowed()) { GEngine->HMDDevice->UpdatePlayerCameraRotation(this, OutVT.POV); } } // Synchronize the actor with the view target results SetActorLocationAndRotation(OutVT.POV.Location, OutVT.POV.Rotation, false); UpdateCameraLensEffects(OutVT); }
void AController::SetInitialLocationAndRotation(const FVector& NewLocation, const FRotator& NewRotation) { SetActorLocationAndRotation(NewLocation, NewRotation); SetControlRotation(NewRotation); }
/** Simulates the free movement of the ball based on proxy states */ void AMagicBattleSoccerBall::ClientSimulateFreeMovingBall() { AMagicBattleSoccerPlayerController* MyPC = Cast<AMagicBattleSoccerPlayerController>(UGameplayStatics::GetPlayerController(GetWorld(), 0)); if (nullptr == MyPC || !MyPC->IsNetworkTimeValid() || 0 == proxyStateCount) { // We don't know yet know what the time is on the server yet so the timestamps // of the proxy states mean nothing; that or we simply don't have any proxy // states yet. Don't do any interpolation. SetActorLocationAndRotation(ServerPhysicsState.pos, ServerPhysicsState.rot); } else { uint64 interpolationBackTime = 100; uint64 extrapolationLimit = 500; // This is the target playback time of the rigid body uint64 interpolationTime = MyPC->GetNetworkTime() - interpolationBackTime; // Use interpolation if the target playback time is present in the buffer if (proxyStates[0].timestamp > interpolationTime) { // Go through buffer and find correct state to play back for (int i=0; i<proxyStateCount; i++) { if (proxyStates[i].timestamp <= interpolationTime || i == proxyStateCount-1) { // The state one slot newer (<100ms) than the best playback state FSmoothPhysicsState rhs = proxyStates[FMath::Max(i - 1, 0)]; // The best playback state (closest to 100 ms old (default time)) FSmoothPhysicsState lhs = proxyStates[i]; // Use the time between the two slots to determine if interpolation is necessary int64 length = (int64)(rhs.timestamp - lhs.timestamp); double t = 0.0F; // As the time difference gets closer to 100 ms t gets closer to 1 in // which case rhs is only used if (length > 1) t = (double)(interpolationTime - lhs.timestamp) / (double)length; // if t=0 => lhs is used directly FVector pos = FMath::Lerp(lhs.pos, rhs.pos, t); FRotator rot = FMath::Lerp(lhs.rot, rhs.rot, t); SetActorLocationAndRotation(pos, rot); return; } } } // Use extrapolation else { FSmoothPhysicsState latest = proxyStates[0]; uint64 extrapolationLength = interpolationTime - latest.timestamp; // Don't extrapolate for more than [extrapolationLimit] milliseconds if (extrapolationLength < extrapolationLimit) { FVector pos = latest.pos + latest.vel * ((float)extrapolationLength * 0.001f); FRotator rot = latest.rot; SetActorLocationAndRotation(pos, rot); } else { // Don't move. If we're this far away from the server, we must be pretty laggy. // Wait to catch up with the server. } } } }