RTS (C++) Camera , Can't get movement working

Hi,

I am trying to create a RTS camera. I followed some tutorial online, but they are all in bp (this works), so I am trying to convert one to C++ since I prefer using that since I know that already. The goal is to have a camera that can rotate/move/zoom etc. Well I my camera is on top of a pawn, which I am moving with my PlayerController class. The pawn code looks like this:

CameraPawn.h


// Fill out your copyright notice in the Description page of Project Settings.
    
    #pragma once
    
    #include "GameFramework/Pawn.h"
    #include "CameraPawn.generated.h"
    
    UCLASS()
    class RTSC_API ACameraPawn : public APawn
    {
    	GENERATED_BODY()
    
    public:
    	// Sets default values for this pawn's properties
    	ACameraPawn();
    
    	// Called when the game starts or when spawned
    	virtual void BeginPlay() override;
    	
    	// Called every frame
    	virtual void Tick( float DeltaSeconds ) override;
    
    	// Called to bind functionality to input
    	virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;
    
    	USpringArmComponent* GetSpringArm();
    
    protected:
    	UPROPERTY(EditAnywhere)
    	USpringArmComponent* m_CameraSpringArm;
    	UCameraComponent* m_Camera;
    	
    };


CameraPawn.cpp


// Fill out your copyright notice in the Description page of Project Settings.
    
    #include "RTSC.h"
    #include "CameraPawn.h"
    
    
    // Sets default values
    ACameraPawn::ACameraPawn()
    {
     	// Set this pawn to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
    	PrimaryActorTick.bCanEverTick = true;
    
    	RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
    	m_CameraSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArm"));
    	m_CameraSpringArm->SetupAttachment(RootComponent);
    	m_CameraSpringArm->SetRelativeLocationAndRotation(FVector(0.0f, 0.0f, 50.0f), FRotator(-60.0f, 0.0f, 0.0f));
    	m_CameraSpringArm->TargetArmLength = 1500.f;
    	m_CameraSpringArm->bEnableCameraLag = true;
    	m_CameraSpringArm->CameraLagSpeed = 3.0f;
    
    	m_Camera = CreateDefaultSubobject<UCameraComponent>(TEXT("GameCamera"));
    	m_Camera->SetupAttachment(m_CameraSpringArm, USpringArmComponent::SocketName);
    
    	UGameplayStatics::GetPlayerController(this, 0);
    }
    
    // Called when the game starts or when spawned
    void ACameraPawn::BeginPlay()
    {
    	Super::BeginPlay();
    	
    }
    
    // Called every frame
    void ACameraPawn::Tick( float DeltaTime )
    {
    	Super::Tick( DeltaTime );
    
    }
    
    // Called to bind functionality to input
    void ACameraPawn::SetupPlayerInputComponent(class UInputComponent* InputComponent)
    {
    	Super::SetupPlayerInputComponent(InputComponent);
    
    }
    
    USpringArmComponent* ACameraPawn::GetSpringArm()
    {
    	if (m_CameraSpringArm != 0)
    		return m_CameraSpringArm;
    	else
    		return 0;
    }

Lots of the code is copy pasted and it looks okay to me.

Now where my problem is this: In the controller before I implented rorating and stuff, I was just changing the pawn’s location. Well that did not work anymore when I started rorating, so I thought about using the transform functions. But I can’t get my head around it how it 100% works. So this is my code at the moment:


// Fill out your copyright notice in the Description page of Project Settings.
    
    #pragma once
    
    #include "GameFramework/PlayerController.h"
    #include "CameraPawnController.generated.h"
    
    /**
     * 
     */
    class ACameraPawn;
    UCLASS()
    class RTSC_API ACameraPawnController : public APlayerController
    {
    	GENERATED_BODY()
    
    public:
    	ACameraPawnController();
    
    	virtual void SetupInputComponent() override;
    	virtual void Tick(float DeltaSeconds) override;
    
    protected:
    
    
    private:
    	ACameraPawn* m_CameraPawn;
    	
    	FVector2D MovementInput;
    	FVector2D CameraInput;
    
    	bool m_ZoomingIn;
    	bool m_ZoomingOut;
    
    	bool m_Panning;
    
    	void MoveForward(float AxisValue);
    	void MoveRight(float AxisValue);
    	void Pancamera();
    	void stop();
    	void ZoomIn();
    	void ZoomOut();
    };

.cpp file


// Fill out your copyright notice in the Description page of Project Settings.
    
    #include "RTSC.h"
    #include "CameraPawnController.h"
    #include "CameraPawn.h"
    
    ACameraPawnController::ACameraPawnController()
    {
    	bShowMouseCursor = true;
    
    	m_ZoomingIn = false;
    	m_ZoomingOut = false;
    	m_Panning = false;
    }
    
    void ACameraPawnController::SetupInputComponent() 
    {
    	Super::SetupInputComponent();
    
    	InputComponent->BindAxis("MoveForward", this, &ACameraPawnController::MoveForward);
    	InputComponent->BindAxis("MoveRight", this, &ACameraPawnController::MoveRight);
    
    	InputComponent->BindAction("ZoomIn" , IE_Pressed, this, &ACameraPawnController::ZoomIn);
    	InputComponent->BindAction("ZoomOut", IE_Pressed, this, &ACameraPawnController::ZoomOut);
    
    	InputComponent->BindAction("Pan", IE_Pressed, this, &ACameraPawnController::Pancamera);
    	InputComponent->BindAction("Pan", IE_Released, this, &ACameraPawnController::stop);
    }
    
    void ACameraPawnController::Tick(float DeltaSeconds)
    {
    	Super::Tick(DeltaSeconds);
    
    	if (!MovementInput.IsZero())
    	{
    		MovementInput = MovementInput.GetSafeNormal() * 1300.0f;
    		FVector NewLocation = GetPawn()->GetActorLocation();
    		
    		NewLocation += GetActorForwardVector() * MovementInput.X * DeltaSeconds;
    		NewLocation += GetActorRightVector() * MovementInput.Y * DeltaSeconds;
    		//GetPawn()->SetActorLocation(NewLocation);
    		
    
    		FVector NewLocation = GetPawn()->GetActorLocation();
    		FTransform NewTransform = GetPawn()->GetActorTransform();
    		NewTransform.SetLocation = NewLocation;
    		GetPawn()->SetActorTransform(NewTransform);
    	}
    
    	if (m_ZoomingIn)
    	{
    		m_ZoomingIn = false;
    
    		ACameraPawn* camera = dynamic_cast<ACameraPawn*>(GetPawn());
    
    		if(camera->GetSpringArm()->TargetArmLength > 500)
    			camera->GetSpringArm()->TargetArmLength -= 110;
    	}
    
    	if (m_ZoomingOut)
    	{
    		m_ZoomingOut = false;
    
    		ACameraPawn* camera = dynamic_cast<ACameraPawn*>(GetPawn());
    
    		if(camera->GetSpringArm()->TargetArmLength < 3000)
    		 camera->GetSpringArm()->TargetArmLength += 110;
    	}
    
    	if (m_Panning)
    	{
    		float x, y;
    		GetInputMouseDelta(x, y);
    		FRotator NewRotator = GetPawn()->GetActorRotation();
    		NewRotator.Yaw += x;
    		NewRotator.Pitch += y;
    
    		NewRotator.Pitch = FMath::Clamp<float>(NewRotator.Pitch, -150, 75);
    
    		GetPawn()->SetActorRelativeRotation(NewRotator);
    
    
    		
    	}
    
    }
    
    void ACameraPawnController::MoveForward(float AxisValue)
    {
    	MovementInput.X = FMath::Clamp<float>(AxisValue, -1.0f, 1.0f);
    }
    
    void  ACameraPawnController::MoveRight(float AxisValue)
    {
    	MovementInput.Y = FMath::Clamp<float>(AxisValue, -1.0f, 1.0f);
    }
    
    void ACameraPawnController::Pancamera()
    {
    	m_Panning = true;
    }
    
    void ACameraPawnController::stop()
    {
    	m_Panning = false;
    }
    
    void ACameraPawnController::ZoomIn()
    {
    	m_ZoomingIn = true;
    }
    
    void ACameraPawnController::ZoomOut()
    {
    	m_ZoomingOut = true;
    }

I know the zoomint/out restriciotn does not work 100% and that I should make all the variables public for bleuprints, but this is currently just to make it work. Maybe Im using the wrong approach here, but if some could give me advice on anything on the code, please do so :slight_smile:

Thanks :slight_smile:

If you’re trying to create an RTS Camera then you should probably check out this Wiki page.
https://wiki.unrealengine.com/RTS_Camera

  • Michael

Thanks for the reply, but that one is using a SpectatorPawn. I read somewhere on the forums that it is preferred to use your own Pawn. Also it does not support rotaing, but maybe it has somethign I need. Thanks a lot, ill take a look at it :slight_smile:

I made a full tutorial based on it, just search the forum for ''tutorial RTS camera c++" and it will be approx the 7th thread found. By the way I will update it in near future