下面這個設置好像只有一個有作用,無法同時控制兩個物體。
//Take control of the default Player
AutoPossessPlayer = EAutoReceiveInput::Player0;
這個程序是讓物體附加一個相機,應該移動和視圖都是針對物體的,和之前的Game-Controlled Cameras還是有區別的,Game-Controlled Camera沒有依附特定的物體,直接寫在程序的兩個變量上進行控制,而這個例子使用的是UCameraComponent,attach到根節點。
放上代碼,和之前的例子沒有什麼區別,那麼這個C++ Programming Tutorials中的七個例子還剩下兩個例子,First Person Shooter Tutorial和User Interface With UMG.這兩個例子暫時先不寫,已經能寫基本的程序,需要弄清楚它們的類是幹什麼的。很明顯的tutorial上有個錯誤是編譯不過的,但是自己參考API修改過來了。
Performing 3 actions (4 in parallel)
@progress 'Compiling C++ source code...' 0%
[2/3] Compile PawnWithCamera.cpp
[1/3] Compile PawnWithCamera.gen.cpp
/home/wang/Documents/Unreal Projects/UnrealLearn/Source/UnrealLearn/PawnWithCamera.cpp:75:43: error:
no member named 'SafeNormal' in 'FVector2D'
MovementInput = MovementInput.SafeNormal() * 100.0f;
~~~~~~~~~~~~~ ^
1 error generated.
@progress 'Compiling C++ source code...' 25%
@progress 'Compiling C++ source code...' 50%
@progress 'Compiling C++ source code...' 75%
可以看到編譯的時候SafeNormal編譯提示上說FVector2D沒有這個方法,所以查看Document發現應該使用GetSafeNormal(),所以會查閱還是很重要的,之前就有很多的頭文件都是通過查找獲取來的,這點官網還做得比較好,附上代碼。
PawnWithCamera.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "GameFramework/SpringArmComponent.h"
#include "Camera/CameraComponent.h"
#include "PawnWithCamera.generated.h"
UCLASS()
class UNREALLEARN_API APawnWithCamera : public APawn
{
GENERATED_BODY()
public:
// Sets default values for this pawn's properties
APawnWithCamera();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
// Called to bind functionality to input
virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
protected:
UPROPERTY(EditAnywhere)
USpringArmComponent* OurCameraSpringArm;
UCameraComponent* OurCamera;
//Input variables
FVector2D MovementInput;
FVector2D CameraInput;
float ZoomFactor;
bool bZoomingIn;
//Input functions
void MoveForward(float AxisValue);
void MoveRight(float AxisValue);
void PitchCamera(float AxisValue);
void YawCamera(float AxisValue);
void ZoomIn();
void ZoomOut();
};
PawnWithCamera.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "PawnWithCamera.h"
// Sets default values
APawnWithCamera::APawnWithCamera()
{
// 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;
//Create our components
RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
OurCameraSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArm"));
OurCameraSpringArm->SetupAttachment(RootComponent);
OurCameraSpringArm->SetRelativeLocationAndRotation(FVector(0.0f, 0.0f, 50.0f), FRotator(-60.0f, 0.0f, 0.0f));
OurCameraSpringArm->TargetArmLength = 400.f;
OurCameraSpringArm->bEnableCameraLag = true;
OurCameraSpringArm->CameraLagSpeed = 3.0f;
OurCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("GameCamera"));
OurCamera->SetupAttachment(OurCameraSpringArm, USpringArmComponent::SocketName);
//Take control of the default Player
AutoPossessPlayer = EAutoReceiveInput::Player0;
}
// Called when the game starts or when spawned
void APawnWithCamera::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void APawnWithCamera::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
//Zoom in if ZoomIn button is down, zoom back out if it's not
{
if (bZoomingIn)
{
ZoomFactor += DeltaTime / 0.5f; //Zoom in over half a second
}
else
{
ZoomFactor -= DeltaTime / 0.25f; //Zoom out over a quarter of a second
}
ZoomFactor = FMath::Clamp<float>(ZoomFactor, 0.0f, 1.0f);
//Blend our camera's FOV and our SpringArm's length based on ZoomFactor
OurCamera->FieldOfView = FMath::Lerp<float>(90.0f, 60.0f, ZoomFactor);
OurCameraSpringArm->TargetArmLength = FMath::Lerp<float>(400.0f, 300.0f, ZoomFactor);
}
//Rotate our actor's yaw, which will turn our camera because we're attached to it
{
FRotator NewRotation = GetActorRotation();
NewRotation.Yaw += CameraInput.X;
SetActorRotation(NewRotation);
}
//Rotate our camera's pitch, but limit it so we're always looking downward
{
FRotator NewRotation = OurCameraSpringArm->GetComponentRotation();
NewRotation.Pitch = FMath::Clamp(NewRotation.Pitch + CameraInput.Y, -80.0f, -15.0f);
OurCameraSpringArm->SetWorldRotation(NewRotation);
}
//Handle movement based on our "MoveX" and "MoveY" axes
{
if (!MovementInput.IsZero())
{
//Scale our movement input axis values by 100 units per second
MovementInput = MovementInput.GetSafeNormal() * 100.0f;
FVector NewLocation = GetActorLocation();
NewLocation += GetActorForwardVector() * MovementInput.X * DeltaTime;
NewLocation += GetActorRightVector() * MovementInput.Y * DeltaTime;
SetActorLocation(NewLocation);
}
}
}
// Called to bind functionality to input
void APawnWithCamera::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
//Hook up events for "ZoomIn"
InputComponent->BindAction("ZoomIn", IE_Pressed, this, &APawnWithCamera::ZoomIn);
InputComponent->BindAction("ZoomIn", IE_Released, this, &APawnWithCamera::ZoomOut);
//Hook up every-frame handling for our four axes
InputComponent->BindAxis("MoveForward", this, &APawnWithCamera::MoveForward);
InputComponent->BindAxis("MoveRight", this, &APawnWithCamera::MoveRight);
InputComponent->BindAxis("CameraPitch", this, &APawnWithCamera::PitchCamera);
InputComponent->BindAxis("CameraYaw", this, &APawnWithCamera::YawCamera);
}
//Input functions
void APawnWithCamera::MoveForward(float AxisValue)
{
MovementInput.X = FMath::Clamp<float>(AxisValue, -1.0f, 1.0f);
}
void APawnWithCamera::MoveRight(float AxisValue)
{
MovementInput.Y = FMath::Clamp<float>(AxisValue, -1.0f, 1.0f);
}
void APawnWithCamera::PitchCamera(float AxisValue)
{
CameraInput.Y = AxisValue;
}
void APawnWithCamera::YawCamera(float AxisValue)
{
CameraInput.X = AxisValue;
}
void APawnWithCamera::ZoomIn()
{
bZoomingIn = true;
}
void APawnWithCamera::ZoomOut()
{
bZoomingIn = false;
}