01 CameraDirector.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "CameraDirector.generated.h"
UCLASS()
class HOWTO_AUTOCAMERA_API ACameraDirector : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
// 为此Actor的属性设置默认值
ACameraDirector();
protected:
// Called when the game starts or when spawned
// 当游戏开始或生成时调用
virtual void BeginPlay() override;
public:
// Called every frame
// 每一帧调用
virtual void Tick(float DeltaTime) override;
//值将不会被重置
//允许我们在 虚幻编辑器 中设置摄像机1(CameraOne)
UPROPERTY(EditAnywhere)
AActor* CameraOne;
//允许我们在 虚幻编辑器 中设置摄像机2(CameraTwo)
UPROPERTY(EditAnywhere)
AActor* CameraTwo;
//UE4,不赋值,系统初始化为0.0f
//C++,全局的变量系统初始化为0,局部的变量则乱码
float TimeToNextCameraChange;
};
02 CameraDirector.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "HowTo_AutoCamera.h"
#include "CameraDirector.h"
//允许我们访问一些有用的通用函数
#include "Kismet/GameplayStatics.h"//加的
// Sets default values
ACameraDirector::ACameraDirector()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
}
// Called when the game starts or when spawned
void ACameraDirector::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
//Tick函数,1帧调一次。一秒60帧,就一秒调60次
void ACameraDirector::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//以下加的
//每隔3秒在两个不同的摄像机间切换默认玩家的视图、
//摄像机停留时间
const float TimeBetweenCameraChanges = 2.0f;
//摄像机平滑过渡的时间
const float SmoothBlendTime = 0.75f;
//DeltaTime与FPS互为倒数
//第1次调用:假设DeltaTime==-0.01,0-0.01=-0.01
//第2次调用:1.99-0.01=1.98
//第3次调用:1.98-0.01=1.97
//1.99/0.01=199,199帧之内都不会切换摄像机
//199/60约等于3.3秒,3.3秒之内都不会切换摄像机,即约3.3秒切换一次摄像机
TimeToNextCameraChange -= DeltaTime;
if (TimeToNextCameraChange <= 0.0f)
{
//-0.01+2=1.99
//小于0之后,加上2
TimeToNextCameraChange += TimeBetweenCameraChanges;
/*
指针APlayerController*(世界中一个物体引用,玩家索引)
class APlayerController* UGameplayStatics::GetPlayerController(const UObject* WorldContextObject, int32 PlayerIndex )
{
if (UWorld* World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::LogAndReturnNull))
{
uint32 Index = 0;
for (FConstPlayerControllerIterator Iterator = World->GetPlayerControllerIterator(); Iterator; ++Iterator)
{
APlayerController* PlayerController = Iterator->Get();
if (Index == PlayerIndex)
{
return PlayerController;
}
Index++;
}
}
return nullptr;
}
*/
// 查找处理本地玩家控制的actor
//好比是手柄、键盘
APlayerController* OurPlayerController = UGameplayStatics::GetPlayerController(this, 0);
if (OurPlayerController)
{
/*
AActor*指针
AActor* APlayerController::GetViewTarget() const
{
return PlayerCameraManager ? PlayerCameraManager->GetViewTarget() : NULL;
}
*/
//获取玩家控制的Camera,不是CameraOne就切回CameraOne
//
if ((OurPlayerController->GetViewTarget() != CameraOne) && (CameraOne != nullptr))
{
// 立即切换到摄像机1。
OurPlayerController->SetViewTarget(CameraOne);
}
//不等于CameraTwo,就是等于CameraOne
else if ((OurPlayerController->GetViewTarget() != CameraTwo) && (CameraTwo != nullptr))
{
// 平滑地切换到CameraTwo
//blend,混合
/*书写不规范是为了可观性
virtual void SetViewTargetWithBlend(
class AActor* NewViewTarget,
float BlendTime = 0, //摄像机平滑过渡的时间
enum EViewTargetBlendFunction BlendFunc = VTBlend_Linear,//混合模式
float BlendExp = 0, bool bLockOutgoing = false
);
//p平滑过渡的模式
//默认缺省值是EViewTargetBlendFunction::VTBlend_Linear
UENUM()
enum EViewTargetBlendFunction
{
//Camera does a simple linear interpolation.
VTBlend_Linear,
//Camera has a slight ease in and ease out, but amount of ease cannot be tweaked.
VTBlend_Cubic,
//Camera immediately accelerates, but smoothly decelerates into the target. Ease amount controlled by BlendExp.
VTBlend_EaseIn,
//Camera smoothly accelerates, but does not decelerate into the target. Ease amount controlled by BlendExp.
VTBlend_EaseOut,
//Camera smoothly accelerates and decelerates. Ease amount controlled by BlendExp.
VTBlend_EaseInOut,
VTBlend_MAX,
};
*/
//OurPlayerController->SetViewTargetWithBlend(CameraTwo, SmoothBlendTime, EViewTargetBlendFunction::VTBlend_MAX);
//OurPlayerController->SetViewTargetWithBlend(CameraTwo);去掉混合时间,切得生硬
OurPlayerController->SetViewTargetWithBlend(CameraTwo, SmoothBlendTime);
}
}
}
}
02 01 混合模式
试试VTBlend_EaseInOut
OurPlayerController->SetViewTargetWithBlend(CameraTwo, SmoothBlendTime, EViewTargetBlendFunction::VTBlend_EaseInOut);
演示(是不是不一样,是不是很卡,总之变了)
02 02 去掉混合时间
OurPlayerController->SetViewTargetWithBlend(CameraTwo);//去掉混合时间,切得生硬