当前位置:网站首页>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(...)
边栏推荐
- 为什么要做特征的归一化/标准化?
- How can I avoid "div/0!" Errors in Google Docs spreadsheet- How do I avoid the '#DIV/0!' error in Google docs spreadsheet?
- [water quality prediction] water quality prediction based on MATLAB Fuzzy Neural Network [including Matlab source code 1923]
- SSM integration - joint debugging of front and rear protocols (list function, add function, add function status processing, modify function, delete function)
- How does if ($variable) work? [repeat] - how exactly does if ($variable) work? [duplicate]
- Simple solution of physical backup and restore of Damon database
- [optics] vortex generation based on MATLAB [including Matlab source code 1927]
- __ Weak and__ The difference between blocks
- Day18 - basis of interface testing
- Record: install MySQL on ubuntu18.04
猜你喜欢
Flutter网络和数据存储框架搭建 -b1
[disease identification] machine vision lung cancer detection system based on Matlab GUI [including Matlab source code 1922]
What does a really excellent CTO look like in my eyes
Web3 credential network project galaxy is better than nym?
EGO Planner代码解析bspline_optimizer部分(3)
application
We have built an intelligent retail settlement platform
What is the content of game modeling
Ctrip will implement a 3+2 work system in March, with 3 days on duty and 2 days at home every week
leetcode:556. Next larger element III [simulation + change as little as possible]
随机推荐
Web Security (VIII) what is CSRF attack? Why can token prevent csdf attacks?
math_泰勒公式
Random numbers in a long range, is that right- Random number in long range, is this the way?
Simulation scheduling problem of SystemVerilog (1)
Php based campus lost and found platform (automatic matching push)
Record: pymysql is used in pycharm to connect to the database
Latex image rotates with title
[proteus simulation] a simple encrypted electronic password lock designed with 24C04 and 1602LCD
[disease identification] machine vision lung cancer detection system based on Matlab GUI [including Matlab source code 1922]
flask 生成swagger文档
The earliest record
SQL injection for Web Security (1)
The most valuable thing
Integrated easy to pay secondary domain name distribution system
SQL custom collation
[optics] dielectric constant calculation based on MATLAB [including Matlab source code 1926]
【光学】基于matlab介电常数计算【含Matlab源码 1926期】
The more you talk, the more your stupidity will be exposed.
Sentinel source code analysis part II - sentinel dashboard console startup and configuration
东数西算拉动千亿产业,敢啃“硬骨头”的存储厂商才更有机会