Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- void UCharacterMovementComponent::PerformMovement(float DeltaSeconds)
- {
- SCOPE_CYCLE_COUNTER(STAT_CharacterMovementPerformMovement);
- if (!HasValidData())
- {
- return;
- }
- // no movement if we can't move, or if currently doing physical simulation on UpdatedComponent
- if (MovementMode == MOVE_None || UpdatedComponent->Mobility != EComponentMobility::Movable || UpdatedComponent->IsSimulatingPhysics())
- {
- return;
- }
- // Force floor update if we've moved outside of CharacterMovement since last update.
- bForceNextFloorCheck |= (IsMovingOnGround() && UpdatedComponent->GetComponentLocation() != LastUpdateLocation);
- // Update saved LastPreAdditiveVelocity with any external changes to character Velocity that happened since last update (jumps, knockbacks, etc.)
- if( CurrentRootMotion.HasAdditiveVelocity() )
- {
- CurrentRootMotion.LastPreAdditiveVelocity += (Velocity-LastUpdateVelocity);
- }
- FVector OldVelocity;
- FVector OldLocation;
- // Scoped updates can improve performance of multiple MoveComponent calls.
- {
- FScopedMovementUpdate ScopedMovementUpdate(UpdatedComponent, bEnableScopedMovementUpdates ? EScopedUpdate::DeferredUpdates : EScopedUpdate::ImmediateUpdates);
- MaybeUpdateBasedMovement(DeltaSeconds);
- OldVelocity = Velocity;
- OldLocation = UpdatedComponent->GetComponentLocation();
- ApplyAccumulatedForces(DeltaSeconds);
- // Check for a change in crouch state. Players toggle crouch by changing bWantsToCrouch.
- const bool bAllowedToCrouch = CanCrouchInCurrentState();
- if ((!bAllowedToCrouch || !bWantsToCrouch) && IsCrouching())
- {
- UnCrouch(false);
- }
- else if (bWantsToCrouch && bAllowedToCrouch && !IsCrouching())
- {
- Crouch(false);
- }
- if (MovementMode == MOVE_NavWalking && bWantsToLeaveNavWalking)
- {
- TryToLeaveNavWalking();
- }
- // Character::LaunchCharacter() has been deferred until now.
- HandlePendingLaunch();
- // Prepare Root Motion (generate/accumulate from root motion sources to be used later)
- if( HasRootMotionSources() && !CharacterOwner->bClientUpdating && !CharacterOwner->bServerMoveIgnoreRootMotion)
- {
- // Animation root motion - If using animation RootMotion, tick animations before running physics.
- if( CharacterOwner->IsPlayingRootMotion() && CharacterOwner->GetMesh() )
- {
- TickCharacterPose(DeltaSeconds);
- // Make sure animation didn't trigger an event that destroyed us
- if (!HasValidData())
- {
- return;
- }
- // For local human clients, save off root motion data so it can be used by movement networking code.
- if( CharacterOwner->IsLocallyControlled() && (CharacterOwner->Role == ROLE_AutonomousProxy) && CharacterOwner->IsPlayingNetworkedRootMotionMontage() )
- {
- CharacterOwner->ClientRootMotionParams = RootMotionParams;
- }
- }
- // Generates root motion to be used this frame from sources other than animation
- {
- SCOPE_CYCLE_COUNTER(STAT_CharacterMovementRootMotionSourceCalculate);
- CurrentRootMotion.PrepareRootMotion(DeltaSeconds, *CharacterOwner, *this, true);
- }
- // For local human clients, save off root motion data so it can be used by movement networking code.
- if( CharacterOwner->IsLocallyControlled() && (CharacterOwner->Role == ROLE_AutonomousProxy) )
- {
- CharacterOwner->SavedRootMotion = CurrentRootMotion;
- }
- }
- // Apply Root Motion to Velocity
- if( CurrentRootMotion.HasOverrideVelocity() || HasAnimRootMotion() )
- {
- // Animation root motion overrides Velocity and currently doesn't allow any other root motion sources
- if( HasAnimRootMotion() )
- {
- // Convert to world space (animation root motion is always local)
- USkeletalMeshComponent * SkelMeshComp = CharacterOwner->GetMesh();
- if( SkelMeshComp )
- {
- // Convert Local Space Root Motion to world space. Do it right before used by physics to make sure we use up to date transforms, as translation is relative to rotation.
- RootMotionParams.Set( SkelMeshComp->ConvertLocalRootMotionToWorld(RootMotionParams.GetRootMotionTransform()) );
- }
- // Then turn root motion to velocity to be used by various physics modes.
- if( DeltaSeconds > 0.f )
- {
- AnimRootMotionVelocity = CalcAnimRootMotionVelocity(RootMotionParams.GetRootMotionTransform().GetTranslation(), DeltaSeconds, Velocity);
- Velocity = ConstrainAnimRootMotionVelocity(AnimRootMotionVelocity, Velocity);
- }
- UE_LOG(LogRootMotion, Log, TEXT("PerformMovement WorldSpaceRootMotion Translation: %s, Rotation: %s, Actor Facing: %s, Velocity: %s")
- , *RootMotionParams.GetRootMotionTransform().GetTranslation().ToCompactString()
- , *RootMotionParams.GetRootMotionTransform().GetRotation().Rotator().ToCompactString()
- , *CharacterOwner->GetActorForwardVector().ToCompactString()
- , *Velocity.ToCompactString()
- );
- }
- else
- {
- // We don't have animation root motion so we apply other sources
- if( DeltaSeconds > 0.f )
- {
- SCOPE_CYCLE_COUNTER(STAT_CharacterMovementRootMotionSourceApply);
- FVector NewVelocity = Velocity;
- CurrentRootMotion.AccumulateOverrideRootMotionVelocity(DeltaSeconds, *CharacterOwner, *this, NewVelocity);
- Velocity = NewVelocity;
- }
- }
- }
- // NaN tracking
- checkCode(ensureMsgf(!Velocity.ContainsNaN(), TEXT("UCharacterMovementComponent::PerformMovement: Velocity contains NaN (%s)\n%s"), *GetPathNameSafe(this), *Velocity.ToString()));
- // Clear jump input now, to allow movement events to trigger it for next update.
- CharacterOwner->ClearJumpInput();
- // change position
- StartNewPhysics(DeltaSeconds, 0);
- if (!HasValidData())
- {
- return;
- }
- // uncrouch if no longer allowed to be crouched
- if (IsCrouching() && !CanCrouchInCurrentState())
- {
- UnCrouch(false);
- }
- if (!HasAnimRootMotion() && !CharacterOwner->IsMatineeControlled())
- {
- PhysicsRotation(DeltaSeconds);
- }
- // Apply Root Motion rotation after movement is complete.
- if( HasAnimRootMotion() )
- {
- const FQuat OldActorRotationQuat = UpdatedComponent->GetComponentQuat();
- const FQuat RootMotionRotationQuat = RootMotionParams.GetRootMotionTransform().GetRotation();
- if( !RootMotionRotationQuat.IsIdentity() )
- {
- const FQuat NewActorRotationQuat = RootMotionRotationQuat * OldActorRotationQuat;
- MoveUpdatedComponent(FVector::ZeroVector, NewActorRotationQuat, true);
- }
- #if !(UE_BUILD_SHIPPING)
- // debug
- if (false)
- {
- const FRotator OldActorRotation = OldActorRotationQuat.Rotator();
- const FVector ResultingLocation = UpdatedComponent->GetComponentLocation();
- const FRotator ResultingRotation = UpdatedComponent->GetComponentRotation();
- // Show current position
- DrawDebugCoordinateSystem(GetWorld(), CharacterOwner->GetMesh()->GetComponentLocation() + FVector(0,0,1), ResultingRotation, 50.f, false);
- // Show resulting delta move.
- DrawDebugLine(GetWorld(), OldLocation, ResultingLocation, FColor::Red, true, 10.f);
- // Log details.
- UE_LOG(LogRootMotion, Warning, TEXT("PerformMovement Resulting DeltaMove Translation: %s, Rotation: %s, MovementBase: %s"),
- *(ResultingLocation - OldLocation).ToCompactString(), *(ResultingRotation - OldActorRotation).GetNormalized().ToCompactString(), *GetNameSafe(CharacterOwner->GetMovementBase()) );
- const FVector RMTranslation = RootMotionParams.GetRootMotionTransform().GetTranslation();
- const FRotator RMRotation = RootMotionParams.GetRootMotionTransform().GetRotation().Rotator();
- UE_LOG(LogRootMotion, Warning, TEXT("PerformMovement Resulting DeltaError Translation: %s, Rotation: %s"),
- *(ResultingLocation - OldLocation - RMTranslation).ToCompactString(), *(ResultingRotation - OldActorRotation - RMRotation).GetNormalized().ToCompactString() );
- }
- #endif // !(UE_BUILD_SHIPPING)
- // Root Motion has been used, clear
- RootMotionParams.Clear();
- }
- // consume path following requested velocity
- bHasRequestedVelocity = false;
- OnMovementUpdated(DeltaSeconds, OldLocation, OldVelocity);
- } // End scoped movement update
- // Call external post-movement events. These happen after the scoped movement completes in case the events want to use the current state of overlaps etc.
- CallMovementUpdateDelegate(DeltaSeconds, OldLocation, OldVelocity);
- MaybeSaveBaseLocation();
- UpdateComponentVelocity();
- const bool bHasAuthority = CharacterOwner && CharacterOwner->HasAuthority();
- // If we move we want to avoid a long delay before replication catches up to notice this change, especially if it's throttling our rate.
- if (bHasAuthority && UNetDriver::IsAdaptiveNetUpdateFrequencyEnabled() && UpdatedComponent)
- {
- const UWorld* MyWorld = GetWorld();
- if (MyWorld && MyWorld->GetTimeSeconds() <= CharacterOwner->NetUpdateTime)
- {
- UNetDriver* NetDriver = MyWorld->GetNetDriver();
- if (NetDriver && NetDriver->IsServer())
- {
- FNetworkObjectInfo* NetActor = NetDriver->GetNetworkActor(CharacterOwner);
- if (NetActor && NetDriver->IsNetworkActorUpdateFrequencyThrottled(*NetActor))
- {
- if (ShouldCancelAdaptiveReplication())
- {
- NetDriver->CancelAdaptiveReplication(*NetActor);
- }
- }
- }
- }
- }
- if (bHasAuthority && UpdatedComponent && !IsNetMode(NM_Client))
- {
- const bool bLocationChanged = (UpdatedComponent->GetComponentLocation() != LastUpdateLocation);
- const bool bRotationChanged = (UpdatedComponent->GetComponentQuat() != LastUpdateRotation);
- if (bLocationChanged || bRotationChanged)
- {
- const UWorld* MyWorld = GetWorld();
- ServerLastTransformUpdateTimeStamp = MyWorld ? MyWorld->GetTimeSeconds() : 0.f;
- }
- }
- LastUpdateLocation = UpdatedComponent ? UpdatedComponent->GetComponentLocation() : FVector::ZeroVector;
- LastUpdateRotation = UpdatedComponent ? UpdatedComponent->GetComponentQuat() : FQuat::Identity;
- LastUpdateVelocity = Velocity;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement