相机系统
整体流程¶
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
函数。
APlayerController::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 map
if (PlayerCameraManagerClass != NULL)
{
PlayerCameraManager = GetWorld()->SpawnActor<APlayerCameraManager>(PlayerCameraManagerClass, SpawnInfo);
}
else
{
PlayerCameraManager = GetWorld()->SpawnActor<APlayerCameraManager>(SpawnInfo);
}
if (PlayerCameraManager != NULL)
{
PlayerCameraManager->InitializeFor(this);
}
else
{
// log
}
每个
PlayerController
都会在世界创建一个 PlayerCameraManager
Actor。 针对每个创建的 PlayerCameraManager
,都会调用 InitializeFor
函数初始化。
APlayerCameraManager::InitializeFor
FMinimalViewInfo DefaultFOVCache = GetCameraCacheView();
DefaultFOVCache.FOV = DefaultFOV;
SetCameraCachePOV(DefaultFOVCache);
PCOwner = PC;
SetViewTarget(PC);
// set the level default scale
SetDesiredColorScale(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
。
UWorld::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();
}
}
}
//...
}
//...
应用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 相对看向目标的各种参数。