Unreal 入门-Montage Root Motion 功能代码说明。

来源:互联网 发布:天猫魔盒如何下载软件 编辑:程序博客网 时间:2024/05/22 03:20

Root Motion 移动功能。

void UCharacterMovementComponent::SimulatedTick(float DeltaSeconds){    SCOPE_CYCLE_COUNTER(STAT_CharacterMovementSimulated);    checkSlow(CharacterOwner != nullptr);    if (NetworkSmoothingMode == ENetworkSmoothingMode::Replay)    {        const FVector OldLocation = UpdatedComponent ? UpdatedComponent->GetComponentLocation() : FVector::ZeroVector;        const FVector OldVelocity = Velocity;        // Interpolate between appropriate samples        {            SCOPE_CYCLE_COUNTER( STAT_CharacterMovementSmoothClientPosition );            SmoothClientPosition( DeltaSeconds );        }        // Update replicated movement mode        ApplyNetworkMovementMode( GetCharacterOwner()->GetReplicatedMovementMode() );        UpdateComponentVelocity();        bJustTeleported = false;        CharacterOwner->RootMotionRepMoves.Empty();        CurrentRootMotion.Clear();        CharacterOwner->SavedRootMotion.Clear();        // Note: we do not call the Super implementation, that runs prediction.        // We do still need to call these though        OnMovementUpdated(DeltaSeconds, OldLocation, OldVelocity);        CallMovementUpdateDelegate(DeltaSeconds, OldLocation, OldVelocity);        LastUpdateLocation = UpdatedComponent ? UpdatedComponent->GetComponentLocation() : FVector::ZeroVector;        LastUpdateRotation = UpdatedComponent ? UpdatedComponent->GetComponentQuat() : FQuat::Identity;        LastUpdateVelocity = Velocity;        //TickCharacterPose( DeltaSeconds );        return;    }    // If we are playing a RootMotion AnimMontage.    if (CharacterOwner->IsPlayingNetworkedRootMotionMontage())    {        bWasSimulatingRootMotion = true;        UE_LOG(LogRootMotion, Verbose, TEXT("UCharacterMovementComponent::SimulatedTick"));        // Tick animations before physics.        if( CharacterOwner->GetMesh() )        {            TickCharacterPose(DeltaSeconds);            // Make sure animation didn't trigger an event that destroyed us            if (!HasValidData())            {                return;            }        }        if( RootMotionParams.bHasRootMotion )        {            const FQuat OldRotationQuat = UpdatedComponent->GetComponentQuat();            const FVector OldLocation = UpdatedComponent->GetComponentLocation();            SimulateRootMotion(DeltaSeconds, RootMotionParams.GetRootMotionTransform());            #if !(UE_BUILD_SHIPPING)            // debug            if (false)            {                const FRotator OldRotation = OldRotationQuat.Rotator();                const FRotator NewRotation = UpdatedComponent->GetComponentRotation();                const FVector NewLocation = UpdatedComponent->GetComponentLocation();                DrawDebugCoordinateSystem(GetWorld(), CharacterOwner->GetMesh()->GetComponentLocation() + FVector(0,0,1), NewRotation, 50.f, false);                DrawDebugLine(GetWorld(), OldLocation, NewLocation, FColor::Red, true, 10.f);                UE_LOG(LogRootMotion, Log,  TEXT("UCharacterMovementComponent::SimulatedTick DeltaMovement Translation: %s, Rotation: %s, MovementBase: %s"),                *(NewLocation - OldLocation).ToCompactString(), *(NewRotation - OldRotation).GetNormalized().ToCompactString(), *GetNameSafe(CharacterOwner->GetMovementBase()) );            }            #endif // !(UE_BUILD_SHIPPING)        }        // then, once our position is up to date with our animation,         // handle position correction if we have any pending updates received from the server.        if( CharacterOwner && (CharacterOwner->RootMotionRepMoves.Num() > 0) )        {            CharacterOwner->SimulatedRootMotionPositionFixup(DeltaSeconds);//这里调整位置跟随动作运动        }    }    //...}


这里做了移动:

void ACharacter::SimulatedRootMotionPositionFixup(float DeltaSeconds){    const FAnimMontageInstance* ClientMontageInstance = GetRootMotionAnimMontageInstance();//这里获取了自带Mesh    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.                            CharacterMovement->bNetworkSmoothingComplete = false;                            CharacterMovement->SmoothCorrection(OldLocation, OldRotation, GetActorLocation(), GetActorQuat());                        }                    }                }            }            // 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);        }    }}

这里获取了Character自带的Mesh,限制的Root Motion只能用在Character 自带的Mesh。

/** Get FAnimMontageInstance playing RootMotion */FAnimMontageInstance * ACharacter::GetRootMotionAnimMontageInstance() const{    return (Mesh && Mesh->GetAnimInstance()) ? Mesh->GetAnimInstance()->GetRootMotionMontageInstance() : NULL;}

0 0
原创粉丝点击