Ejemplo n.º 1
0
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);
        }
    }
}
Ejemplo n.º 2
0
void ADynamicWeather::AdjustSunPositionBasedOnActorRotation()
{
  const FVector Direction = - GetActorQuat().GetForwardVector();
  const FVector2D SphericalCoords = Direction.UnitCartesianToSpherical();
  Weather.SunPolarAngle = FMath::RadiansToDegrees(SphericalCoords.X);
  Weather.SunAzimuthAngle = FMath::RadiansToDegrees(SphericalCoords.Y);
}
Ejemplo n.º 3
0
void ACharacter::SimulatedRootMotionPositionFixup(float DeltaSeconds)
{
    const FAnimMontageInstance* ClientMontageInstance = GetRootMotionAnimMontageInstance();
    if( ClientMontageInstance && CharacterMovement && Mesh )
    {
        // Find most recent buffered move that we can use.
        const int32 MoveIndex = FindRootMotionRepMove(*ClientMontageInstance);
        if( MoveIndex != INDEX_NONE )
        {
            const FVector OldLocation = GetActorLocation();
            const FQuat OldRotation = GetActorQuat();
            // Move Actor back to position of that buffered move. (server replicated position).
            const FSimulatedRootMotionReplicatedMove& RootMotionRepMove = RootMotionRepMoves[MoveIndex];
            if( RestoreReplicatedMove(RootMotionRepMove) )
            {
                const float ServerPosition = RootMotionRepMove.RootMotion.Position;
                const float ClientPosition = ClientMontageInstance->GetPosition();
                const float DeltaPosition = (ClientPosition - ServerPosition);
                if( FMath::Abs(DeltaPosition) > KINDA_SMALL_NUMBER )
                {
                    // Find Root Motion delta move to get back to where we were on the client.
                    const FTransform LocalRootMotionTransform = ClientMontageInstance->Montage->ExtractRootMotionFromTrackRange(ServerPosition, ClientPosition);

                    // Simulate Root Motion for delta move.
                    if( CharacterMovement )
                    {
                        const float MontagePlayRate = ClientMontageInstance->GetPlayRate();
                        // Guess time it takes for this delta track position, so we can get falling physics accurate.
                        if (!FMath::IsNearlyZero(MontagePlayRate))
                        {
                            const float DeltaTime = DeltaPosition / MontagePlayRate;

                            // Even with negative playrate deltatime should be positive.
                            check(DeltaTime > 0.f);
                            CharacterMovement->SimulateRootMotion(DeltaTime, LocalRootMotionTransform);

                            // After movement correction, smooth out error in position if any.
                            INetworkPredictionInterface* PredictionInterface = Cast<INetworkPredictionInterface>(GetMovementComponent());
                            if (PredictionInterface)
                            {
                                PredictionInterface->SmoothCorrection(OldLocation, OldRotation);
                            }
                        }
                    }
                }
            }

            // Delete this move and any prior one, we don't need them anymore.
            UE_LOG(LogRootMotion, Log,  TEXT("\tClearing old moves (%d)"), MoveIndex+1);
            RootMotionRepMoves.RemoveAt(0, MoveIndex+1);
        }
    }
}
Ejemplo n.º 4
0
void ACharacter::PostNetReceiveLocationAndRotation()
{
    if( Role == ROLE_SimulatedProxy )
    {
        // Don't change transform if using relative position (it should be nearly the same anyway, or base may be slightly out of sync)
        if (!ReplicatedBasedMovement.HasRelativeLocation())
        {
            const FVector OldLocation = GetActorLocation();
            const FQuat OldRotation = GetActorQuat();
            UpdateSimulatedPosition(ReplicatedMovement.Location, ReplicatedMovement.Rotation);

            INetworkPredictionInterface* PredictionInterface = Cast<INetworkPredictionInterface>(GetMovementComponent());
            if (PredictionInterface)
            {
                PredictionInterface->SmoothCorrection(OldLocation, OldRotation);
            }
        }
    }
}
Ejemplo n.º 5
0
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());
		}
	}
}