一、接口在游戏线程被调用时:
cpp
AActor::SetActorLocation
-> RootComponent->MoveComponent
-> InternalSetWorldLocationAndRotation
-> 计算 RelativeLocation / RelativeRotation
-> UpdateComponentToWorldWithParent
-> CalcNewComponentToWorld
-> ComponentToWorld = NewTransform
-> PropagateTransformUpdate
-> UpdateBounds
-> OnUpdateTransform
-> TransformUpdated.Broadcast
// 标记这个组件为Dirty
-> MarkRenderTransformDirty
-> MarkForNeededEndOfFrameUpdate
//将这个组件加入到一个数组中,在帧末时 来调用
-> MarkActorComponentForNeededEndOfFrameUpdate
-> UpdateChildTransforms
二、在帧末时:
cpp
UWorld::SendAllEndOfFrameUpdates
-> DoDeferredRenderUpdates_Concurrent
-> SendRenderTransform_Concurrent
-> FSceneInterface::UpdatePrimitiveTransform
-> FScene::UpdatePrimitiveTransform
//创建了一个RenderCommand添加到渲染线程执行
-> ENQUEUE_RENDER_COMMAND( UpdateTransformCommand )
最终会更新渲染线程侧的 Primitive Proxy 状态
Tip: ENQUEUE_RENDER_COMMAND( UpdateTransformCommand ) 这个宏传入的是值类型的数据,并且在Render Thread 会把这些值类型赋值给Primitive Proxy。然后在RenderThread中,Primitive Proxy提供渲染数据,从而避免GameThread 和RenderThread 的数据读写冲突
附加一个具体的代码
cpp
ENQUEUE_RENDER_COMMAND(UpdateTransformCommand)(
[UpdateParams](FRHICommandListBase&)
{
FScopeCycleCounter Context(UpdateParams.PrimitiveSceneProxy->GetStatId());
UpdateParams.Scene->UpdatePrimitiveTransform_RenderThread(
UpdateParams.PrimitiveSceneProxy,
UpdateParams.WorldBounds,
UpdateParams.LocalBounds,
UpdateParams.LocalToWorld,
UpdateParams.AttachmentRootPosition,
UpdateParams.PreviousTransform
);
if (FSimpleStreamableAssetManager::IsEnabled())
{
const FPrimitiveSceneProxy* SceneProxy = UpdateParams.PrimitiveSceneProxy;
FSimpleStreamableAssetManager::Update(
FSimpleStreamableAssetManager::FUpdate
{
SceneProxy,
SceneProxy->SimpleStreamableAssetManagerIndex,
UpdateParams.WorldBounds,
SceneProxy->GetMinDrawDistance(),
SceneProxy->GetMaxDrawDistance(),
SceneProxy->PrimitiveSceneInfo->LastRenderTime,
SceneProxy->IsForceMipStreaming()
}
);
}
}
);