当前位置:网站首页>UE source code analysis: uccharactermovementcomponent - rootmotion
UE source code analysis: uccharactermovementcomponent - rootmotion
2022-07-03 19:15:00 【JK Chen】
brief introduction
RootMotion In two parts : From animation RootMotion And customization RootMotionSource
UCharacterMovementComponent::ApplyRootMotionSource
original edition CMC Mutually exclusive use both
RootMotion By changing Velocity Act on CMC, The main code is UCharacterMovementComponent::PerformMovement Inside
Data flow
Data on ,AnimInstance Inside FAnimMontageInstance Relevant data are :
/** AnimMontage instances that are running currently * - only one is primarily active per group, and the other ones are blending out */
TArray<struct FAnimMontageInstance*> MontageInstances;
/** Map between Active Montages and their FAnimMontageInstance */
TMap<class UAnimMontage*, struct FAnimMontageInstance*> ActiveMontagesMap;
/** Active Root Motion Montage Instance, if any. */
struct FAnimMontageInstance* RootMotionMontageInstance;
adopt RootMotionMontageInstance Get current RootMotion Corresponding Montage
float UAnimInstance::Montage_Play(UAnimMontage* MontageToPlay, float InPlayRate/*= 1.f*/, EMontagePlayReturnType ReturnValueType, float InTimeToStartMontageAt, bool bStopAllMontages /*= true*/)
if (MontageToPlay->HasRootMotion())
RootMotionMontageInstance = NewInstance;
FAnimMontageInstance * ACharacter::GetRootMotionAnimMontageInstance() const
return (Mesh && Mesh->GetAnimInstance()) ? Mesh->GetAnimInstance()->GetRootMotionMontageInstance() : nullptr;
AnimInstance Deal with FRootMotionMovementParams
Update process : bones - Animation blueprint - Montage - RootMotion
void USkeletalMeshComponent::TickAnimation(float DeltaTime, bool bNeedsValidRootMotion)
void UAnimInstance::UpdateAnimation(float DeltaSeconds, bool bNeedsValidRootMotion, EUpdateAnimationFlag UpdateFlag)
void UAnimInstance::UpdateMontage(float DeltaSeconds)
void UAnimInstance::Montage_Advance(float DeltaSeconds)
void FAnimMontageInstance::Advance(float DeltaTime, struct FRootMotionMovementParams* OutRootMotionParams, bool bBlendRootMotion)
// take Mesh Of RootMotion The accumulation of (FTransform Multiply) To RootMotionParams
OutRootMotionParams->Accumulate(RootMotion);
Save to :
// Root motion read from proxy (where it is calculated) and stored here to avoid potential stalls by calling GetProxyOnGameThread
FRootMotionMovementParams UAnimInstance::ExtractedRootMotion;
CMC Use FRootMotionMovementParams
FRootMotionMovementParams USkeletalMeshComponent::ConsumeRootMotion()
FRootMotionMovementParams USkeletalMeshComponent::ConsumeRootMotion_Internal(float InAlpha)
FRootMotionMovementParams UAnimInstance::ConsumeExtractedRootMotion(float Alpha)
ExtractedRootMotion
Move inside the component FRootMotionMovementParams
/** Root Motion movement params. Holds result of anim montage root motion during PerformMovement(), and is overridden * during autonomous move playback to force historical root motion for MoveAutonomous() calls */
UPROPERTY(Transient)
FRootMotionMovementParams RootMotionParams;
This deposit is procedural AnimRootMotion, Whether there is AnimRootMotion Also use this to judge , from ExtractedRootMotion Cumulative
bool UCharacterMovementComponent::HasAnimRootMotion() const
return RootMotionParams.bHasRootMotion;
Applied to the CMC The process of
void UCharacterMovementComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
void UCharacterMovementComponent::PerformMovement(float DeltaSeconds)
void UCharacterMovementComponent::TickCharacterPose(float DeltaTime)
// to update ExtractedRootMotion
void USkeletalMeshComponent::TickPose(float DeltaTime, bool bNeedsValidRootMotion)
void USkeletalMeshComponent::TickAnimation(float DeltaTime, bool bNeedsValidRootMotion)
// obtain ExtractedRootMotion
FRootMotionMovementParams RootMotion = CharacterMesh->ConsumeRootMotion();
if (RootMotion.bHasRootMotion)
{
RootMotion.ScaleRootMotionTranslation(CharacterOwner->GetAnimRootMotionTranslationScale());
// Accumulate inside the mobile component
RootMotionParams.Accumulate(RootMotion);
}
// Handle RootMotionSource
CurrentRootMotion.PrepareRootMotion(DeltaSeconds, *CharacterOwner, *this, true);
// Use Override RootMotionSource perhaps RootMotionParams Update speed
if( CurrentRootMotion.HasOverrideVelocity() || HasAnimRootMotion() )
// Use RootMotionParams
if( HasAnimRootMotion() )
// direct override by AnimRootMotion Of Velocity
AnimRootMotionVelocity = CalcAnimRootMotionVelocity(RootMotionParams.GetRootMotionTransform().GetTranslation(), DeltaSeconds, Velocity);
Velocity = ConstrainAnimRootMotionVelocity(AnimRootMotionVelocity, Velocity);
// Use Override RootMotionSource
else
CurrentRootMotion.AccumulateOverrideRootMotionVelocity(DeltaSeconds, *CharacterOwner, *this, NewVelocity);
Velocity = NewVelocity;
// Update location ( See the analysis below )
void UCharacterMovementComponent::StartNewPhysics(float deltaTime, int32 Iterations)
void UCharacterMovementComponent::PhysWalking(float deltaTime, int32 Iterations)
// Update rotation
if( HasAnimRootMotion() )
MoveUpdatedComponent(FVector::ZeroVector, NewActorRotationQuat, true);
else if (CurrentRootMotion.HasActiveRootMotionSources())
MoveUpdatedComponent(FVector::ZeroVector, NewActorRotationQuat, true);
If you go RootMotionSource Words , stay PerformMovement It did Override,PhysWalking Do inside Override and Additive, The one outside here is redundant
void UCharacterMovementComponent::PhysWalking(float deltaTime, int32 Iterations)
while ( (remainingTime >= MIN_TICK_TIME) && (Iterations < MaxSimulationIterations) && CharacterOwner && (CharacterOwner->Controller || bRunPhysicsWithNoController || HasAnimRootMotion() || CurrentRootMotion.HasOverrideVelocity() || (CharacterOwner->GetLocalRole() == ROLE_SimulatedProxy)) )
RestorePreAdditiveRootMotionVelocity();
void UCharacterMovementComponent::ApplyRootMotionToVelocity(float deltaTime)
// application AnimRootMotion
if( HasAnimRootMotion() && deltaTime > 0.f )
Velocity = ConstrainAnimRootMotionVelocity(AnimRootMotionVelocity, Velocity);
return;
// application Override RootMotionSource
if( CurrentRootMotion.HasOverrideVelocity() )
CurrentRootMotion.AccumulateOverrideRootMotionVelocity(deltaTime, *CharacterOwner, *this, Velocity);
// application Additive RootMotionSource
if( CurrentRootMotion.HasAdditiveVelocity() )
CurrentRootMotion.AccumulateAdditiveRootMotionVelocity(deltaTime, *CharacterOwner, *this, Velocity);
// Movement and other subsequent processing
MoveAlongFloor(MoveVelocity, timeTick, &StepDownResult);
Network synchronization
From Montage and RootMotionSource Two parts
The first part is due to AnimInstance On the client side , So naturally, it is synchronous
The second part ,ApplyRootMotionSource Will be added to CurrentRootMotion(FRootMotionSourceGroup) Of PendingAddRootMotionSources Inside
CMC Of PerformMovement In the use of RootMotion We'll call FRootMotionSourceGroup::PrepareRootMotion,RootMotionSources.Append(PendingAddRootMotionSources);
// Sync CurrentRootMotion
void ACharacter::PreReplication( IRepChangedPropertyTracker & ChangedPropertyTracker )
RepRootMotion.AuthoritativeRootMotion = CharacterMovement->CurrentRootMotion;
UPROPERTY(ReplicatedUsing=OnRep_RootMotion)
struct FRepRootMotionMontage ACharacter::RepRootMotion;
// The analog end uses the synchronized RepRootMotion
void ACharacter::OnRep_RootMotion()
if (GetLocalRole() == ROLE_SimulatedProxy)
RootMotionRepMoves.AddZeroed(1);
// Analog end at SimulatedTick Will use RootMotionRepMoves Realization RootMotion
FSimulatedRootMotionReplicatedMove& NewMove = RootMotionRepMoves.Last();
NewMove.RootMotion = RepRootMotion;
correct
int32 UNetDriver::ServerReplicateActors(float DeltaSeconds)
PlayerController->SendClientAdjustment()
if (RemotePawn && (RemotePawn->GetRemoteRole() == ROLE_AutonomousProxy) && !IsNetMode(NM_Client))
{
INetworkPredictionInterface* NetworkPredictionInterface = Cast<INetworkPredictionInterface>(RemotePawn->GetMovementComponent());
if (NetworkPredictionInterface)
{
// Main control end
NetworkPredictionInterface->SendClientAdjustment();
}
}
void UCharacterMovementComponent::SendClientAdjustment()
if (CurrentRootMotion.HasActiveRootMotionSources())
ClientAdjustRootMotionSourcePosition(...)
else if (bIsPlayingNetworkedRootMotionMontage)
ClientAdjustRootMotionPosition(...)
边栏推荐
- OSPF - detailed explanation of stub area and full stub area
- Day18 - basis of interface testing
- Record: solve the problem that MySQL is not an internal or external command environment variable
- Sustainable service business models
- Integrated easy to pay secondary domain name distribution system
- User identity used by startup script and login script in group policy
- Recommend a GIF processing artifact less than 300K - gifsicle (free download)
- 我們做了一個智能零售結算平臺
- SSM integration - joint debugging of front and rear protocols (list function, add function, add function status processing, modify function, delete function)
- This Chinese numpy quick look-up table is too easy!
猜你喜欢

Flutter网络和数据存储框架搭建 -b1

SSM整合-前后台协议联调(列表功能、添加功能、添加功能状态处理、修改功能、删除功能)

Sentinel source code analysis part I sentinel overview

为什么要做特征的归一化/标准化?

The earliest record

【水质预测】基于matlab模糊神经网络水质预测【含Matlab源码 1923期】

Record: pymysql is used in pycharm to connect to the database

【疾病识别】基于matlab GUI机器视觉肺癌检测系统【含Matlab源码 1922期】

FBI警告:有人利用AI换脸冒充他人身份进行远程面试

In addition to the prickles that pierce your skin, there are poems and distant places that originally haunt you in plain life
随机推荐
我们做了一个智能零售结算平台
Go home early today
SSM integration - joint debugging of front and rear protocols (list function, add function, add function status processing, modify function, delete function)
Streaming media server (16) -- figure out the difference between live broadcast and on-demand
Which do MySQL and Oracle learn?
[proteus simulation] a simple encrypted electronic password lock designed with 24C04 and 1602LCD
Webrtc[41] - Analysis of the establishment process of webrtc transmission channel
[leetcode weekly race] game 300 - 6110 Number of incremental paths in the grid graph - difficult
The way to treat feelings
leetcode:11. 盛最多水的容器【双指针 + 贪心 + 去除最短板】
“google is not defined” when using Google Maps V3 in Firefox remotely
Recommend a GIF processing artifact less than 300K - gifsicle (free download)
Random numbers in a long range, is that right- Random number in long range, is this the way?
Day18 - basis of interface testing
Integrated easy to pay secondary domain name distribution system
Next spread
Nous avons fait une plateforme intelligente de règlement de détail
math_泰勒公式
Floating source code comment (38) parallel job processor
Sentinel source code analysis part II - sentinel dashboard console startup and configuration