612 字
3 分钟
相机系统
文章目录
整体流程
UE的相机系统相比于更加复杂,涉及到 CameraComponent,CameraActor,PlayerController,PlayerCameraManager 几个类。
classDiagram UWorld --> APlayerController UGameViewportClient --> ULocalPlayer : 渲染画面时获取摄像机的POV ULocalPlayer --> APlayerController : 获取POV APlayerController "1" <--> "1" APlayerCameraManager : APlayerController创建并驱动PlayerCameraManager APlayerCameraManager ..> AActor : 更新ViewTarget AActor o--> UCameraComponent : 计算POV APlayerCameraManager <--> UCameraModifier : 最后修改POV UCameraModifier --> UCameraModifier_CameraShake : 示例说明
class UWorld { +Tick(...) }
class UGameViewportClient { +Draw() }
class ULocalPlayer { +CalcSceneView(...) +GetViewPoint(...) }
class APlayerController { +SpawnPlayerCameraManager() +UpdateCameraManager() +GetPlayerViewPoint(...) }
class APlayerCameraManager { +UpdateCamera(...) +UpdateViewTarget(...) +GetCameraCacheView() }
class AActor { +CalcCamera() }
class UCameraComponent { +GetCameraView(...) }
class UCameraModifier { +ModifyCamera() }
class UCameraModifier_CameraShake { }- CameraActor
CameraComponent的包装容器,以使相机可以放置在关卡中。
- CameraComponent
- 代表相机的各种数据。
- 并不直接处理数据。
- PlayerCameraManager
- 相机系统的核心,处理相机数据并应用到
ViewTarget。 - 管理 ViewTarget,记录摄像机跟随对象Target和摄像机POV。
- 相机系统的核心,处理相机数据并应用到
总体流程上:
- 初始化ViewTarget:
PlayerController 会在 PostInitializeComponents 函数中调用 SpawnPlayerCameraManager 函数。
SpawnPlayerCameraManager
// servers and owning clients get cameras// If no archetype specified, spawn an Engine.PlayerCameraManager. NOTE all games should specify an archetype.FActorSpawnParameters SpawnInfo;SpawnInfo.Owner = this;SpawnInfo.Instigator = GetInstigator();SpawnInfo.ObjectFlags |= RF_Transient; // We never want to save camera managers into a mapif (PlayerCameraManagerClass != NULL){ PlayerCameraManager = GetWorld()->SpawnActor<APlayerCameraManager>(PlayerCameraManagerClass, SpawnInfo);}else{ PlayerCameraManager = GetWorld()->SpawnActor<APlayerCameraManager>(SpawnInfo);}
if (PlayerCameraManager != NULL){ PlayerCameraManager->InitializeFor(this);}else{ // log}-
每个
PlayerController都会在世界创建一个PlayerCameraManagerActor。 -
针对每个创建的
PlayerCameraManager,都会调用InitializeFor函数初始化。
InitializeFor
FMinimalViewInfo DefaultFOVCache = GetCameraCacheView();DefaultFOVCache.FOV = DefaultFOV;SetCameraCachePOV(DefaultFOVCache);
PCOwner = PC;
SetViewTarget(PC);
// set the level default scaleSetDesiredColorScale(GetWorldSettings()->DefaultColorScale, 5.f);
// Force camera update so it doesn't sit at (0,0,0) for a full tick.// This can have side effects with streaming.UpdateCamera(0.f);- 更新ViewTarget:
UWorld 会在 Tick 函数中调用 AplayerController::UpdateCameraManager,驱动 PlayerCameraManager::UpdateCamera 更新 ViewTarget。
World Tick
//...
for (int32 i = 0; i < LevelCollections.Num(); ++i){ //... // Update cameras last. This needs to be done before NetUpdates, and after all actors have been ticked. for( FConstPlayerControllerIterator Iterator = GetPlayerControllerIterator(); Iterator; ++Iterator ) { if (APlayerController* PlayerController = Iterator->Get()) { if (!bIsPaused || PlayerController->ShouldPerformFullTickWhenPaused()) { PlayerController->UpdateCameraManager(DeltaSeconds); } else if (PlayerController->PlayerCameraManager && FCameraPhotographyManager::IsSupported(this)) { PlayerController->PlayerCameraManager->UpdateCameraPhotographyOnly(); } } } //...}//...PlayerController UpdateCameraManager
if (PlayerCameraManager != NULL){ PlayerCameraManager->UpdateCamera(DeltaSeconds);}PlayerCameraManager UpdateCamera
if ((PCOwner->Player && PCOwner->IsLocalPlayerController()) || !bUseClientSideCameraUpdates || bDebugClientSideCamera){ DoUpdateCamera(DeltaTime); //...}- 应用ViewTarget:
UGameViewportClient 的 Draw 方法渲染画面时,会通过 ULocalPlayer::CalcSceneView 方法,最终从 APlayerCameraManager 中获取 ViewTarget 中的POV数据用于渲染。
处理ViewTarget
FViewTarget 在 APlayerCameraManager::UpdateViewTarget 函数中进行更新。ViewTarget核心关注两个参数。
- Target 相机看向的目标,后面的POV基于此进行计算。
USTRUCT(BlueprintType)struct FTViewTarget{ // ... /** Target Actor used to compute POV */ UPROPERTY(EditAnywhere, BlueprintReadWrite, Category=TViewTarget) TObjectPtr<class AActor> Target; // ...};- POV 相对看向目标的各种参数。