Hi Mikhail,
Well if I understand your problem correctly it’s easier than mine back then.
You want to be able to switch “camera Mode” within your playerController am I right ?
If so, you can do this. (I use that concept in my own games)
customPlayerCameraManager.h
#pragma once
#include "Camera/PlayerCameraManager.h"
//#include "BaseCameraMode.h"
#include "Object.h"
#include "ProtoPlayerCameraManager.generated.h"
class UBaseCameraMode;
UCLASS()
class PROTO_API AProtoPlayerCameraManager : public APlayerCameraManager
{
GENERATED_BODY()
private:
UPROPERTY()
UBaseCameraMode* _currentCameraMode;
UPROPERTY()
TArray<UBaseCameraMode*> _cameraModes;
bool _isCameraIsInterpoling;
void UpdateViewTarget(FTViewTarget& outVT, float deltaTime) override;
void BeginPlay() override;
void CreateCameraModesAndSetupInitial();
UBaseCameraMode* CreateCameraMode(UClass* cameraModeClass);
public:
AProtoPlayerCameraManager();
void LimitCameraPitch(FRotator& rotation, float minPitch, float maxPitch);
void UpdatePitch(float value);
void UpdateYaw(float value);
void ChangeCameraMode(int cameraMode);
};
//Note. Include here because nested UCLASS and source declared UCLASS are not supported en date du 07/08/2015 sur 4.8.3 and I want to reduce includes and references
/******* Camera Modes *******/
/******* Base Mode *******/
UCLASS(Abstract)
class PROTO_API UBaseCameraMode : public UObject
{
GENERATED_BODY()
protected:
float _minPitchAngle, _maxPitchAngle;
UPROPERTY()
FVector _relativePosition;
UPROPERTY()
FRotator _rotation;
UPROPERTY()
FRotator _defaultRotation;
UPROPERTY()
AProtoPlayerCameraManager* _camera;
public:
UBaseCameraMode();
UFUNCTION()
virtual void UpdateViewTarget(FTViewTarget& outVT, float deltaTime) PURE_VIRTUAL(UBaseCameraMode::UpdateViewTarget,);
UFUNCTION()
virtual void SetRotationAndRelatedStuff(FRotator oldDefaultRotation) PURE_VIRTUAL (UBaseCameraMode::SetRotationAndRelatedStuff,);
UFUNCTION()
virtual bool InterpolateIn(FTViewTarget& outVT, float deltaTime, float interpolationSpeed) PURE_VIRTUAL(UBaseCameraMode::InterpolateIn, return false;);
virtual void UpdateYaw(float value);
virtual void UpdatePitch(float value);
void SetCamera(AProtoPlayerCameraManager* camera);
FORCEINLINE FRotator GetDefaultRotation()const
{
return _defaultRotation;
}
};
/******* Third person Mode *******/
UCLASS()
class PROTO_API UThirdPersonCameraMode : public UBaseCameraMode
{
GENERATED_BODY()
public:
UThirdPersonCameraMode();
UFUNCTION()
void UpdateViewTarget(FTViewTarget& outVT, float deltaTime);
UFUNCTION()
void SetRotationAndRelatedStuff(FRotator oldDefaultRotation);
UFUNCTION()
bool InterpolateIn(FTViewTarget& outVT, float deltaTime, float interpolationSpeed);
void DoCollisionTest(FVector& desiredLocation);
};
/******* Shoulder Mode *******/
UCLASS()
class PROTO_API UShoulderCameraMode : public UBaseCameraMode
{
GENERATED_BODY()
private:
UPROPERTY()
FRotator _rotationDelta;
public:
UShoulderCameraMode();
UFUNCTION()
void UpdateViewTarget(FTViewTarget& outVT, float deltaTime);
UFUNCTION()
void SetRotationAndRelatedStuff(FRotator oldDefaultRotation);
UFUNCTION()
bool InterpolateIn(FTViewTarget& outVT, float deltaTime, float interpolationSpeed);
void UpdateYaw(float value) override;
};
customPlayerCameraManager.cpp
#include "Proto.h"
#include "ProtoPlayerCameraManager.h"
//#include "BaseCameraMode.h"
//#include "ThirdPersonCameraMode.h"
//#include "ShoulderCameraMode.h"
AProtoPlayerCameraManager::AProtoPlayerCameraManager()
{
_isCameraIsInterpoling = false;
}
void AProtoPlayerCameraManager::BeginPlay()
{
Super::BeginPlay();
CreateCameraModesAndSetupInitial();
}
void AProtoPlayerCameraManager::UpdateViewTarget(FTViewTarget& outVT, float deltaTime)
{
if (_isCameraIsInterpoling)
_isCameraIsInterpoling = _currentCameraMode->InterpolateIn(outVT, deltaTime, 20.0f);
else
_currentCameraMode->UpdateViewTarget(outVT, deltaTime);
}
void AProtoPlayerCameraManager::UpdatePitch(float value)
{
_currentCameraMode->UpdatePitch(value);
}
void AProtoPlayerCameraManager::UpdateYaw(float value)
{
_currentCameraMode->UpdateYaw(value);
}
void AProtoPlayerCameraManager::LimitCameraPitch(FRotator& rotation, float minPitch, float maxPitch)
{
LimitViewPitch(rotation, minPitch, maxPitch);
}
UBaseCameraMode* AProtoPlayerCameraManager::CreateCameraMode(UClass* cameraModeClass)
{
UBaseCameraMode* cameraMode = NewObject<UBaseCameraMode>(GetTransientPackage(), cameraModeClass);
cameraMode->SetCamera(this);
return cameraMode;
}
void AProtoPlayerCameraManager::CreateCameraModesAndSetupInitial()
{
_cameraModes.Add(CreateCameraMode(UThirdPersonCameraMode::StaticClass()));
_cameraModes.Add(CreateCameraMode(UShoulderCameraMode::StaticClass()));
_currentCameraMode = _cameraModes[0];
}
void AProtoPlayerCameraManager::ChangeCameraMode(int cameraMode)
{
FRotator oldDefaultRotation = _currentCameraMode->GetDefaultRotation();
_currentCameraMode = _cameraModes[cameraMode];
_currentCameraMode->SetRotationAndRelatedStuff(oldDefaultRotation);
_isCameraIsInterpoling = true;
}
/******* Camera Modes *******/
/******* Base Mode *********/
UBaseCameraMode::UBaseCameraMode()
{
}
void UBaseCameraMode::UpdatePitch(float value)
{
_rotation.Pitch += value;
_camera->LimitCameraPitch(_rotation, _minPitchAngle, _maxPitchAngle);
}
void UBaseCameraMode::UpdateYaw(float value)
{
_rotation.Yaw += value;
}
void UBaseCameraMode::SetCamera(AProtoPlayerCameraManager* camera)
{
_camera = camera;
}
/******* Third Person Mode *********/
UThirdPersonCameraMode::UThirdPersonCameraMode()
{
_relativePosition = FVector(-200.0f, 0.0f, 0.0f);
_rotation = FRotator(0.0f);
_defaultRotation = _rotation;
_maxPitchAngle = 25.0f;
_minPitchAngle = -50.0f;
}
void UThirdPersonCameraMode::UpdateViewTarget(FTViewTarget& outVT, float deltaTime)
{
FVector finalLocation, characterLocation;
FRotator finalRotation;
characterLocation = outVT.Target->GetActorLocation();
FRotationMatrix cameraRotation(FRotator(_rotation.Pitch, _rotation.Yaw, 0.f));
finalLocation = characterLocation + cameraRotation.TransformPosition(_relativePosition);
DoCollisionTest(finalLocation);
finalRotation = (characterLocation - finalLocation).Rotation();
outVT.POV.Location = finalLocation;
outVT.POV.Rotation = finalRotation;
}
void UThirdPersonCameraMode::SetRotationAndRelatedStuff(FRotator oldDefaultRotation)
{
_rotation = _defaultRotation;
_rotation.Yaw += _camera->GetCameraRotation().Yaw - oldDefaultRotation.Yaw;
}
bool UThirdPersonCameraMode::InterpolateIn(FTViewTarget& outVT, float deltaTime, float interpolationSpeed)
{
FRotator actualRotation = outVT.POV.Rotation;
FRotator outRotation = FMath::RInterpTo(actualRotation, _rotation, deltaTime, interpolationSpeed);
if (outRotation.Equals(_rotation, 1))
outRotation = _rotation;
FVector actualPosition = outVT.POV.Location;
FRotationMatrix cameraRotation(FRotator(_rotation.Pitch, _rotation.Yaw, 0.f));
FVector desiredPosition = outVT.Target->GetActorLocation() + cameraRotation.TransformPosition(_relativePosition);
FVector outPosition = FMath::VInterpTo(actualPosition, desiredPosition, deltaTime, interpolationSpeed);
if (outPosition.Equals(desiredPosition, 1))
outPosition = desiredPosition;
outVT.POV.Location = outPosition;
outVT.POV.Rotation = outRotation;
if ((outPosition == desiredPosition) && (outRotation == _rotation))
return false;
return true;
}
void UThirdPersonCameraMode::DoCollisionTest(FVector& desiredLocation)
{
FCollisionQueryParams traceParams = FCollisionQueryParams(FName(TEXT("Trace")), true, _camera->GetViewTargetPawn());
traceParams.bTraceComplex = true;
traceParams.bTraceAsyncScene = true;
traceParams.bReturnPhysicalMaterial = true;
FHitResult hit(ForceInit);
UWorld* world = _camera->();
FVector characterLocation = _camera->GetViewTargetPawn()->GetActorLocation();
world->SweepSingleByChannel(hit, characterLocation, desiredLocation, FQuat::Identity, ECC_Camera, FCollisionShape::MakeSphere(12.0f), traceParams);
if (hit.bBlockingHit)
desiredLocation = hit.Location;
}
/******* Shoulder Mode *********/
UShoulderCameraMode::UShoulderCameraMode()
{
_relativePosition = FVector(-93.0f, 65.0f, 78.0f);
_rotation = FRotator(0.0f, 10.0f, 0.0f);
_defaultRotation = _rotation;
_rotationDelta = FRotator(0.0f);
_maxPitchAngle = 10.0f;
_minPitchAngle = -20.0f;
}
void UShoulderCameraMode::UpdateViewTarget(FTViewTarget& outVT, float deltaTime)
{
FRotationMatrix cameraRotation(FRotator(0.f, _rotationDelta.Yaw, 0.f));
//outVT.POV.Location = outVT.Target->GetActorLocation() + cameraRotation.TransformPosition(_relativePosition);
outVT.POV.Location = outVT.Target->GetActorLocation() + _relativePosition;
outVT.POV.Rotation = _rotation;
}
void UShoulderCameraMode::SetRotationAndRelatedStuff(FRotator oldDefaultRotation)
{
_rotation = _defaultRotation;
_rotation.Yaw += _camera->GetCameraRotation().Yaw;
_rotationDelta.Yaw = _camera->GetCameraRotation().Yaw;
_rotationDelta.Pitch = _rotation.Roll = 0.0f;
}
bool UShoulderCameraMode::InterpolateIn(FTViewTarget& outVT, float deltaTime, float interpolationSpeed)
{
FRotator actualRotation = outVT.POV.Rotation;
FRotator outRotation = FMath::RInterpTo(actualRotation, _rotation, deltaTime, interpolationSpeed);
if (outRotation.Equals(_rotation, 1))
{
outRotation = _rotation;
_rotationDelta = actualRotation;
}
FVector actualPosition = outVT.POV.Location;
FRotationMatrix cameraRotation(FRotator(0.f, _rotationDelta.Yaw, 0.f));
FVector desiredPosition = outVT.Target->GetActorLocation() + cameraRotation.TransformPosition(_relativePosition);
FVector outPosition = FMath::VInterpTo(actualPosition, desiredPosition, deltaTime, interpolationSpeed);
if (outPosition.Equals(desiredPosition, 1))
outPosition = desiredPosition;
outVT.POV.Location = outPosition;
outVT.POV.Rotation = outRotation;
if ((outPosition == desiredPosition) && (outRotation == _rotation))
return false;
return true;
}
void UShoulderCameraMode::UpdateYaw(float value)
{
Super::UpdateYaw(value);
_rotationDelta.Yaw += value;
}
playerController.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "Proto.h"
#include "ProtoPlayerController.h"
#include "InputChord.h"
#include "Engine.h"
#include "ProtoPlayerCameraManager.h"
AProtoPlayerController::AProtoPlayerController()
{
PlayerCameraManagerClass = AProtoPlayerCameraManager::StaticClass();
_cameraMoveSpeed = 100.0f;
}
void AProtoPlayerController::Possess(APawn* pawn)
{
_pawn = CastChecked<AProtoCharacter>(pawn);
Super::Possess(pawn);
}
void AProtoPlayerController::SetupInputComponent()
{
Super::SetupInputComponent();
InputComponent->BindAxis("MoveForward", this, &AProtoPlayerController::MoveForward);
InputComponent->BindAxis("MoveSide", this, &AProtoPlayerController::MoveSide);
InputComponent->BindAxis("Turn", this, &AProtoPlayerController::Turn);
InputComponent->BindAxis("LookUp", this, &AProtoPlayerController::LookUp);
InputComponent->BindAction("ChangeMode", IE_Pressed, this, &AProtoPlayerController::ChangeMode<1>);
InputComponent->BindAction("ChangeMode", IE_Released, this, &AProtoPlayerController::ChangeMode<0>);
InputComponent->BindKey(EKeys::T, IE_Pressed, this, &AProtoPlayerController::CenterCharacter);
}
void AProtoPlayerController::MoveForward(float value)
{
if (value != 0.0)
_pawn->MoveForward(value);
}
void AProtoPlayerController::MoveSide(float value)
{
if (value != 0.0)
_pawn->MoveSide(value);
}
void AProtoPlayerController::Turn(float value)
{
Cast<AProtoPlayerCameraManager>(PlayerCameraManager)->UpdateYaw(value * ()->GetDeltaSeconds() * _cameraMoveSpeed);
_pawn->Turn(value * ()->GetDeltaSeconds() * _cameraMoveSpeed);
}
void AProtoPlayerController::LookUp(float value)
{
Cast<AProtoPlayerCameraManager>(PlayerCameraManager)->UpdatePitch(value * ()->GetDeltaSeconds() * _cameraMoveSpeed);
}
void AProtoPlayerController::CenterCharacter()
{
_pawn->_needToRotate = true;
}
void AProtoPlayerController::ChangeMode(int newmode)
{
_pawn->_needToRotate = true;
_pawn->_onShoulderMode = !_pawn->_onShoulderMode;
_pawn->GetCharacterMovement()->bOrientRotationToMovement = !_pawn->GetCharacterMovement()->bOrientRotationToMovement;
Cast<AProtoPlayerCameraManager>(PlayerCameraManager)->ChangeCameraMode(newmode);
if (GEngine)
GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, FString::Printf(TEXT("Camera Yaw: %f"), Cast<AProtoPlayerCameraManager>(PlayerCameraManager)->GetCameraRotation().Yaw));
}
If you want to actually “switch active player controller” I can provide you the code from another project.
If you have any questions, let me know. I’ll help you.
Help that help you.
Have a good day.
gamer08