CameraActor에 실제 카메라와 관련된 세팅이 추가된 Actor. (ACameraActor를 상속받는다.)
CameraActor는 모니터 기능, CineCameraActor는 영화 촬영용이라고 생각하면 된다.
(Cinema : 영화, 영화 제작, 영화관)
CineCameraActor는 영화 촬영 역할에 걸맞게 Actor를 트래킹하는 기능이 있다.
CineCameraActor와 CameraActor가 Editor의 Detail 창에서 표시되는 내용 |
---|
CineCameraActor의 경우 카메라 세팅 항목이 추가되어 있다 |
---|
참고자료
Unreal Engine Document
https://docs.unrealengine.com/4.27/ko/AnimatingObjects/Sequencer/Cameras/CineCameraActors/
https://docs.unrealengine.com/4.27/en-US/AnimatingObjects/Sequencer/Cameras/CineCameraActors/
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "GameFramework/Actor.h"
#include "Engine/Scene.h"
#include "CameraActor.generated.h"
class UCameraAnim;
/**
* A CameraActor is a camera viewpoint that can be placed in a level.
*/
UCLASS(ClassGroup=Common, hideCategories=(Input, Rendering), showcategories=("Input|MouseInput", "Input|TouchInput"), Blueprintable)
class ENGINE_API ACameraActor : public AActor
{
GENERATED_UCLASS_BODY()
private:
/** Specifies which player controller, if any, should automatically use this Camera when the controller is active. */
UPROPERTY(Category="AutoPlayerActivation", EditAnywhere)
TEnumAsByte<EAutoReceiveInput::Type> AutoActivateForPlayer;
private:
/** The camera component for this camera */
UPROPERTY(Category = CameraActor, VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
class UCameraComponent* CameraComponent;
UPROPERTY(Category = CameraActor, VisibleAnywhere, BlueprintReadOnly, meta = (AllowPrivateAccess = "true"))
class USceneComponent* SceneComponent;
public:
/** If this CameraActor is being used to preview a CameraAnim in the editor, this is the anim being previewed. */
TWeakObjectPtr<class UCameraAnim> PreviewedCameraAnim;
/** Returns index of the player for whom we auto-activate, or INDEX_NONE (-1) if disabled. */
UFUNCTION(BlueprintCallable, Category="AutoPlayerActivation")
int32 GetAutoActivatePlayerIndex() const;
private:
UPROPERTY()
uint32 bConstrainAspectRatio_DEPRECATED:1;
UPROPERTY()
float AspectRatio_DEPRECATED;
UPROPERTY()
float FOVAngle_DEPRECATED;
UPROPERTY()
float PostProcessBlendWeight_DEPRECATED;
UPROPERTY()
struct FPostProcessSettings PostProcessSettings_DEPRECATED;
public:
//~ Begin UObject Interface
virtual void Serialize(FArchive& Ar) override;
#if WITH_EDITOR
virtual void PostLoadSubobjects(FObjectInstancingGraph* OuterInstanceGraph) override;
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
#endif
virtual class USceneComponent* GetDefaultAttachComponent() const override;
//~ End UObject Interface
protected:
//~ Begin AActor Interface
virtual void BeginPlay() override;
//~ End AActor Interface
public:
/** Returns CameraComponent subobject **/
class UCameraComponent* GetCameraComponent() const { return CameraComponent; }
/**
* Called to notify that this camera was cut to, so it can update things like interpolation if necessary.
* Typically called by the camera component.
*/
virtual void NotifyCameraCut() {};
};
// Copyright Epic Games, Inc. All Rights Reserved.
#include "Camera/CameraActor.h"
#include "Engine/World.h"
#include "Kismet/GameplayStatics.h"
#include "Camera/CameraComponent.h"
#include "Camera/CameraAnim.h"
#define LOCTEXT_NAMESPACE "CameraActor"
//////////////////////////////////////////////////////////////////////////
// ACameraActor
ACameraActor::ACameraActor(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
SceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT("SceneComponent"));
// Make the scene component the root component
RootComponent = SceneComponent;
// Setup camera defaults
CameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("CameraComponent"));
CameraComponent->FieldOfView = 90.0f;
CameraComponent->bConstrainAspectRatio = true;
CameraComponent->AspectRatio = 1.777778f;
CameraComponent->PostProcessBlendWeight = 1.0f;
CameraComponent->SetupAttachment(SceneComponent);
// Initialize deprecated properties (needed for backwards compatibility due to delta serialization)
FOVAngle_DEPRECATED = 90.0f;
bConstrainAspectRatio_DEPRECATED = true;
AspectRatio_DEPRECATED = 1.777778f;
PostProcessBlendWeight_DEPRECATED = 1.0f;
// End of deprecated property initialization
}
void ACameraActor::Serialize(FArchive& Ar)
{
Super::Serialize(Ar);
if ((Ar.UE4Ver() < VER_UE4_CAMERA_ACTOR_USING_CAMERA_COMPONENT) && Ar.IsLoading())
{
CameraComponent->bConstrainAspectRatio = bConstrainAspectRatio_DEPRECATED;
CameraComponent->ProjectionMode = ECameraProjectionMode::Perspective;
CameraComponent->AspectRatio = AspectRatio_DEPRECATED;
CameraComponent->FieldOfView = FOVAngle_DEPRECATED;
CameraComponent->PostProcessBlendWeight = PostProcessBlendWeight_DEPRECATED;
CameraComponent->PostProcessSettings = PostProcessSettings_DEPRECATED;
}
}
#if WITH_EDITOR
void ACameraActor::PostLoadSubobjects(FObjectInstancingGraph* OuterInstanceGraph)
{
USceneComponent* OldRoot = RootComponent;
USceneComponent* OldAttachParent = OldRoot->GetAttachParent();
const FName OldSocketName = OldRoot->GetAttachSocketName();
Super::PostLoadSubobjects(OuterInstanceGraph);
if (GetLinkerUE4Version() < VER_UE4_CAMERA_ACTOR_USING_CAMERA_COMPONENT)
{
CameraComponent->SetupAttachment(OldAttachParent, OldSocketName);
OldRoot->SetupAttachment(nullptr);
}
if (GetLinkerUE4Version() < VER_UE4_CAMERA_COMPONENT_ATTACH_TO_ROOT)
{
RootComponent = SceneComponent;
if (OldAttachParent != SceneComponent)
{
CameraComponent->SetupAttachment(RootComponent);
RootComponent->SetupAttachment(OldAttachParent, OldSocketName);
}
}
}
void ACameraActor::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
{
Super::PostEditChangeProperty(PropertyChangedEvent);
if (PreviewedCameraAnim.IsValid() && CameraComponent)
{
PreviewedCameraAnim->BaseFOV = CameraComponent->FieldOfView;
PreviewedCameraAnim->BasePostProcessSettings = CameraComponent->PostProcessSettings;
PreviewedCameraAnim->BasePostProcessBlendWeight = CameraComponent->PostProcessBlendWeight;
}
}
#endif
USceneComponent* ACameraActor::GetDefaultAttachComponent() const
{
return CameraComponent;
}
int32 ACameraActor::GetAutoActivatePlayerIndex() const
{
if (AutoActivateForPlayer != EAutoReceiveInput::Disabled)
{
const int32 PlayerIndex = int32(AutoActivateForPlayer.GetValue()) - 1;
return PlayerIndex;
}
else
{
return INDEX_NONE;
}
}
void ACameraActor::BeginPlay()
{
if (AutoActivateForPlayer != EAutoReceiveInput::Disabled && GetNetMode() != NM_Client)
{
const int32 PlayerIndex = GetAutoActivatePlayerIndex();
// Always put it in the pool of available auto-activate cameras.
GetWorld()->RegisterAutoActivateCamera(this, PlayerIndex);
// If we find a matching PC, bind to it immediately.
APlayerController* PC = UGameplayStatics::GetPlayerController(this, PlayerIndex);
if (PC)
{
PC->SetViewTarget(this);
}
}
Super::BeginPlay();
}
#undef LOCTEXT_NAMESPACE
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "UObject/ObjectMacros.h"
#include "Camera/CameraActor.h"
#include "CineCameraActor.generated.h"
class UCineCameraComponent;
/** Settings to control the camera's lookat feature */
USTRUCT(BlueprintType)
struct FCameraLookatTrackingSettings
{
GENERATED_USTRUCT_BODY()
FCameraLookatTrackingSettings()
: bEnableLookAtTracking(false)
, bDrawDebugLookAtTrackingPosition(false)
, LookAtTrackingInterpSpeed(0.f)
, LastLookatTrackingRotation(FRotator::ZeroRotator)
, RelativeOffset(FVector::ZeroVector)
, bAllowRoll(false)
{
}
/** True to enable lookat tracking, false otherwise. */
UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category = "LookAt")
uint8 bEnableLookAtTracking : 1;
/** True to draw a debug representation of the lookat location */
UPROPERTY(Transient, EditAnywhere, BlueprintReadWrite, Category = "LookAt")
uint8 bDrawDebugLookAtTrackingPosition : 1;
/** Controls degree of smoothing. 0.f for no smoothing, higher numbers for faster/tighter tracking. */
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "LookAt")
float LookAtTrackingInterpSpeed;
/** Last known lookat tracking rotation (used during interpolation) */
FRotator LastLookatTrackingRotation;
/** If set, camera will track this actor's location */
UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category = "LookAt")
TSoftObjectPtr<AActor> ActorToTrack;
/** Offset from actor position to look at. Relative to actor if tracking an actor, relative to world otherwise. */
UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category = "LookAt")
FVector RelativeOffset;
/** True to allow user-defined roll, false otherwise. */
UPROPERTY(Interp, EditAnywhere, BlueprintReadWrite, Category = "LookAt")
uint8 bAllowRoll : 1;
};
/**
* A CineCameraActor is a CameraActor specialized to work like a cinematic camera.
*/
UCLASS(ClassGroup = Common, hideCategories = (Input, Rendering, AutoPlayerActivation), showcategories = ("Input|MouseInput", "Input|TouchInput"), Blueprintable)
class CINEMATICCAMERA_API ACineCameraActor : public ACameraActor
{
GENERATED_BODY()
public:
// Ctor
ACineCameraActor(const FObjectInitializer& ObjectInitializer);
virtual void Tick(float DeltaTime) override;
virtual bool ShouldTickIfViewportsOnly() const override;
virtual void PostInitializeComponents() override;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Current Camera Settings")
FCameraLookatTrackingSettings LookatTrackingSettings;
/** Returns the CineCameraComponent of this CineCamera */
UFUNCTION(BlueprintCallable, Category="Camera")
UCineCameraComponent* GetCineCameraComponent() const { return CineCameraComponent; }
protected:
/** Set to true to skip any interpolations on the next update. Resets to false automatically. */
uint8 bResetInterplation : 1;
FVector GetLookatLocation() const;
virtual void NotifyCameraCut() override;
bool ShouldTickForTracking() const;
private:
/** Returns CineCameraComponent subobject **/
class UCineCameraComponent* CineCameraComponent;
};
// Copyright Epic Games, Inc. All Rights Reserved.
#include "CineCameraActor.h"
#include "DrawDebugHelpers.h"
#include "CineCameraComponent.h"
#define LOCTEXT_NAMESPACE "CineCameraActor"
//////////////////////////////////////////////////////////////////////////
// ACameraActor
ACineCameraActor::ACineCameraActor(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer
.SetDefaultSubobjectClass<UCineCameraComponent>(TEXT("CameraComponent"))
)
{
CineCameraComponent = Cast<UCineCameraComponent>(GetCameraComponent());
PrimaryActorTick.bCanEverTick = true;
SetActorTickEnabled(true);
}
void ACineCameraActor::PostInitializeComponents()
{
Super::PostInitializeComponents();
LookatTrackingSettings.LastLookatTrackingRotation = GetActorRotation();
}
bool ACineCameraActor::ShouldTickIfViewportsOnly() const
{
return true;
}
FVector ACineCameraActor::GetLookatLocation() const
{
FVector FinalLookat;
if (AActor* ActorToTrack = LookatTrackingSettings.ActorToTrack.Get())
{
FTransform const BaseTransform = ActorToTrack->GetActorTransform();
FinalLookat = BaseTransform.TransformPosition(LookatTrackingSettings.RelativeOffset);
}
else
{
FinalLookat = LookatTrackingSettings.RelativeOffset;
}
return FinalLookat;
}
static const FColor DebugLookatTrackingPointSolidColor(200, 200, 32, 128); // yellow
static const FColor DebugLookatTrackingPointOutlineColor = FColor::Black;
void ACineCameraActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (GetCameraComponent() && ShouldTickForTracking())
{
if (LookatTrackingSettings.bEnableLookAtTracking)
{
// do the lookat tracking
// #note this will turn the whole actor, which assumes the cameracomponent's transform is the same as the root component
// more complex component hierarchies will require different handling here
FVector const LookatLoc = GetLookatLocation();
FVector const ToLookat = LookatLoc - GetActorLocation();
FRotator FinalRot =
bResetInterplation
? ToLookat.Rotation()
: FMath::RInterpTo(LookatTrackingSettings.LastLookatTrackingRotation, ToLookat.Rotation(), DeltaTime, LookatTrackingSettings.LookAtTrackingInterpSpeed);
if (LookatTrackingSettings.bAllowRoll)
{
FinalRot.Roll = GetActorRotation().Roll;
}
SetActorRotation(FinalRot);
// we store this ourselves in case other systems try to change our rotation, and end fighting the interpolation
LookatTrackingSettings.LastLookatTrackingRotation = FinalRot;
#if ENABLE_DRAW_DEBUG
if (LookatTrackingSettings.bDrawDebugLookAtTrackingPosition)
{
::DrawDebugSolidBox(GetWorld(), LookatLoc, FVector(12.f), DebugLookatTrackingPointSolidColor);
::DrawDebugBox(GetWorld(), LookatLoc, FVector(12.f), DebugLookatTrackingPointOutlineColor);
}
#endif // ENABLE_DRAW_DEBUG
}
}
bResetInterplation = false;
}
void ACineCameraActor::NotifyCameraCut()
{
Super::NotifyCameraCut();
bResetInterplation = true;
}
bool ACineCameraActor::ShouldTickForTracking() const
{
bool bShouldTickForTracking =
LookatTrackingSettings.bEnableLookAtTracking ||
CineCameraComponent->FocusSettings.TrackingFocusSettings.bDrawDebugTrackingFocusPoint;
#if WITH_EDITORONLY_DATA
if (CineCameraComponent->FocusSettings.bDrawDebugFocusPlane)
{
bShouldTickForTracking = true;
}
#endif // WITH_EDITORONLY_DATA
return bShouldTickForTracking;
}
#undef LOCTEXT_NAMESPACE