C++ Programming Tutorials_4翻译

来源:互联网 发布:淘宝客短网址生成 编辑:程序博客网 时间:2024/06/05 10:16


所在原文目录结构位置:

C++ Programming Guide

 |_____Programming Quick Start Guide

 |_____Introduction to C++ Programming in UE4

 |_____C++ Programming Tutorials

 |_____Managing Game Code

 |_____Development Setup

 |_____Gameplay Programming

 |_____Engine Architecture

 |_____Console Manager: Console Variables in C++

 |_____Command-Line Arguments

 |_____Assertions

 |_____Blueprint Function Libraries

 |_____Unreal Build System

 |_____Plugins

 |_____Coding Standard

 |_____Symbol Debugger


原文地址:Player-Controlled Cameras


-------------------------------------------------------------------------------------------------------------------------------------------------------


C++ Programming Tutorials

C++编程教程

1.Player Input and Pawns 玩家输入和Pawn(个人感觉Pawn是副角色,配角) 

 见译文:  C++ Programming Tutorials_1 


2.Game-Controlled Cameras 游戏控制摄像机

见译文:C++ Programming Tutorials 2


3.Variables, Timers, and Events 变量,定时器和事件

见译文:C++ Programming Tutorials 3

4.Player-Controlled Cameras 玩家控制摄像机

This tutorial will show you how to activate a camera, and change your active camera from one to another.

本教程展示如何激活一个摄像机,和在摄像机之间切换激活.


   1.Attach A Camera To A Pawn  绑定一个摄像机到Pawn

           !!!If you are new to Unreal Engine 4, you might want to read ourProgramming Quick Start tutorial first. For this tutorial, we will assume you are familiar with creating a project, adding C++ code to it, compiling your code, and adding Components to Actors in the Unreal Engine editor.

           !!!如果你是新手,请先翻阅前面对应的译文.

           ①We will begin by creating a new, Basic Code project, with starter content, named "HowTo_PlayerCamera". We'll want to create a custom Pawn class, so let's do that first. For this tutorial, we'll use the name "PawnWithCamera" for our new Pawn class.

            我们先从新创建一个新的,C++基础代码,具有初学者内容的项目开始,项目命名为"HowTo_PlayerCamera".我们要创建一个Pawn 类,在本教程,我们用PawnWithCamera"来命名我们新建的Pawn 类.


           ②Next, in Visual Studio, we should openPawnWithCamera.h and add the following code to the bottom of our class definition:

            接下来,在VS,我们打开PawnWithCamera.h,添加如下代码到类定义的最后:

  

protected:    UPROPERTY(EditAnywhere)    USpringArmComponent* OurCameraSpringArm;    UCameraComponent* OurCamera;

      We will use these variables to create a SpringArmComponent with a CameraComponent attached to the end. Spring arms are a good, simple way to attach cameras (or other Components) so that they're not overly rigid and feel more fluid as they move.

      我们将用这些变量来创建一个SpringArmComponent(减震杆组件),并附加一个CameraComponent.减震杆是好的,简单的附加上摄像机(或者其他Components)以致于它们不会那么僵化,移动起来更流畅一些

           ③After that, we actually need to create our Components in our constructor. Add the following code toPawnWithCamera.cpp inside of APawnWithCamera::APawnWithCamera:

           之后,我们实际上需要在构造函数中创建我们的Components ,添加如下代码到PawnWithCamera.cpp ,APawnWithCamera::APawnWithCamera里面:

//Create our componentsRootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));//创建根组件OurCameraSpringArm = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraSpringArm"));//创建<span class="web-item">减震杆组件</span>OurCameraSpringArm->AttachTo(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;//延迟速度3秒

            This creates a basic, empty SceneComponent as the root of our Component hierarchy, then creates and attaches a SpringArmComponent to it. The Spring Arm is then set at a default pitch of -60 degrees (that is, looking 60 degrees downward) and a position of 50 units above the root. We also establish a few values specific to the SpringArmComponent class that will determine its length and the smoothness of its motion. With that finished, we simply need to create and attach a CameraComponent to the socket on the end of the SpringArmComponent, as follows:

            这将创建一个基本的,空的SceneComponent ,作为我们的组件层次结构的根,然后为它创建和附加一个SpringArmComponent .Spring Arm 默认设置为倾斜角-60°,相对于root 50单位的距离.我们也可以设定一些值来指定SpringArmComponent 类决定它的长度和平滑的运动,这部完成,我们只需要简单地创建和附加一个CameraComponent到插槽,在SpringArmComponent的最后,如下:

OurCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("GameCamera"));OurCamera->AttachTo(OurCameraSpringArm, USpringArmComponent::SocketName);


           ④Finally, we can set our Pawn to be controlled by the default, local player automatically upon being spawned by adding this piece of code:

            最后,我们设置Pawn 为默认控制,该玩家需添加这段代码:

//Take control of the default PlayerAutoPossessPlayer = EAutoReceiveInput::Player0;

We now have a simple Pawn that will allow us to control our camera comfortably. Next, we'll configure our input in the Unreal Engine editor and create code that reacts to it.

我们现在已经有了一个简单的Pawn ,让我们更好的控制我们的摄像机.下一步,我们要配置我们的UE编辑器的输入,创建代码,对输入作出反映.


Work-In-Progress Code     :

      PawnWithCamera.h

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.#pragma once#include "GameFramework/Pawn.h"#include "PawnWithCamera.generated.h"UCLASS()class HOWTO_PLAYERCAMERA_API APawnWithCamera : public APawn{    GENERATED_BODY()public:    // Sets default values for this pawn's properties    APawnWithCamera();    // 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;protected:    UPROPERTY(EditAnywhere)    USpringArmComponent* OurCameraSpringArm;    UCameraComponent* OurCamera;};

PawnWithCamera.cpp

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.#include "HowTo_PlayerCamera.h"#include "PawnWithCamera.h"// Sets default valuesAPawnWithCamera::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->AttachTo(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->AttachTo(OurCameraSpringArm, USpringArmComponent::SocketName);    //Take control of the default Player    AutoPossessPlayer = EAutoReceiveInput::Player0;}// Called when the game starts or when spawnedvoid APawnWithCamera::BeginPlay(){    Super::BeginPlay();}// Called every framevoid APawnWithCamera::Tick( float DeltaTime ){    Super::Tick( DeltaTime );}// Called to bind functionality to inputvoid APawnWithCamera::SetupPlayerInputComponent(class UInputComponent* InputComponent){    Super::SetupPlayerInputComponent(InputComponent);}

2.Configure Input To Control The Camera 配置输入来控制摄像机

①We need to decide what our camera controls will do, and then set up inputs accordingly. For this project, let's allow our follow distance to shorten and field of view to zoom in when the right mouse button is held down. Let's also control our viewing angle with the mouse, and our Pawn's movement with the WASD keys. To do this, we'll open the Project Settings from the Edit dropdown menu in the Unreal Engine editor.

我们需要确定我们的相机控制将做什么,然后建立相应的输入,在本项目,让我们遵从按下鼠标右键距离缩短和视野放大.我们也通过鼠标来控制摄像机的视角,和Pawn的通过WASD键的移动.要做这些,我们需要打开UE编辑器菜单栏的Edit(编辑)->Project Settings (项目设置)

 ②We will need to define one Action Mapping and four Axis Mappings as follows

我们需要定义动作映射和轴映射如下所示

          !!!If you would like to understand more about how input mappings work, you may want to consult thePlayer Input and Pawns tutorial.

         !!!如果你想知道更多关于输入映射,参见Player Input and Pawns

Now that we have defined our input, we need to write some code to react to it. We'll head back to Visual Studio to do that next

既然我们已经定义了输入,我们需要写一些代码来实现输入了,下一步,我们切换到VS

3. Write C++ Code To React To Input

①Our game now has input mappings that we can use, so let's set up some member variables to store the data we receive. During our update, we'll need to know the values of our movement and mouse-looking axes, each of which are two-dimensional vectors. We'll also want to know whether we should be moving toward our zoomed-in or zoomed-out view, and how far between those two states we currently are. To accomplish this, we should add the following code to our class definition

我们游戏已经有输入映射了,所以,我们设置一些成员变量来保存接受的数据,在我们的更新中,我们需要知道位移和旋转角度,他们都是vector,我们也需要知道是否我们应该朝着放大或缩放视图,和我们这两个状态之间的距离有多远.要完成这些,我们需要在PawnWithCamera.h类定义最后添加如下代码

//Input variables

FVector2D MovementInput;

FVector2D CameraInput;

float ZoomFactor;

bool bZoomingIn;

       ②We'll need to create functions to track our input, so let's add the following to our class definition inPawnWithCamera.h as well:

         我们需要创建函数来跟踪我们的输入,所以,让我们还要添加如下代码到我们的PawnWithCamera.h文件:

//Input functionsvoid MoveForward(float AxisValue);void MoveRight(float AxisValue);void PitchCamera(float AxisValue);void YawCamera(float AxisValue);void ZoomIn();void ZoomOut();

And we can now fill these functions out in PawnWithCamera.cpp with the following code:

PawnWithCamera.cpp 文件中实现这些函数:

//Input functionsvoid 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;}

         !!!We haven't done anything with ZoomFactor yet. That variable will be updated during ourPawn'sTick function, since its value changes constantly over time based to the state of a button.

         !!!我们还没有处理ZoomFactor(缩放因子).这个变量将在Pawn的Tick 函数中被更新,因为它作为一个按钮的状态,值不断地变化.
           

       ③Now that we have code that will store our input data, we just need to tellUnreal Engine when to call that code. Binding functions to input events forPawn**s is as simple as adding binding code toAPawnWithCamera::SetupPlayerInputComponent**, as follows:

        既然我们能保存输入的数据了,我们只要告诉UE引擎什么时候调用这些代码就行了.绑定输入函数,如下:

//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 axesInputComponent->BindAxis("MoveForward", this, &APawnWithCamera::MoveForward);InputComponent->BindAxis("MoveRight", this, &APawnWithCamera::MoveRight);InputComponent->BindAxis("CameraPitch", this, &APawnWithCamera::PitchCamera);InputComponent->BindAxis("CameraYaw", this, &APawnWithCamera::YawCamera);

       ④Finally, we can use those values in our Tick function to update our Pawn and Camera each frame. The following code blocks should all be added to APawnWithCamera::Tick inPawnWithCamera.cpp:

       最后,我们能用这些值,在Tick 函数中每一帧更新我们的Pawn和Camera .在PawnWithCamera.cpp的APawnWithCamera::Tick函数添加如下代码:

//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);}

         !!!This code uses several hard-coded values, like the half-second and quarter-second zoom times, the 90-degree zoomed-out and 60-degree zoomed-in field of view values, and the 400 zoomed-out and 300 zoomed-in camera distances. Values like this should generally be exposed to the editor as variables tagged with UPROPERTY(EditAnywhere) so that non-programmers can change them, or so that programmers can change them without recompiling code, or even while playing the game in the editor.

         !!!这段代码使用一些硬编码的值,像放大了1/2倍,1/4倍,视角90度变化,60度变化,相机距离400,300.像这些变量值应该用宏UPROPERTY(EditAnywhere)暴露到编辑器中,这样,非编程人员就可以修改它了,或者说,程序员修改他们也不用修改C++代码了.

//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);}

This block of code rotates our Pawn's yaw directly with the mouse's X axis, but only the camera system responds to the pitch changes from the mouse's Y axis. Rotating anyActor orActor subclass actually rotates the root-levelComponent, which indirectly affects everything attached to it.

这块代码实现了鼠标x轴控制Pawn的偏航,但是只有相机系统从鼠标Y.响应俯仰改变,旋转一些Actor或者Actor的子类实际旋转了根组件,间接影响附加在上面的一切.


//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.SafeNormal() * 100.0f;        FVector NewLocation = GetActorLocation();        NewLocation += GetActorForwardVector() * MovementInput.X * DeltaTime;        NewLocation += GetActorRightVector() * MovementInput.Y * DeltaTime;        SetActorLocation(NewLocation);    }}

Using GetActorForwardVector and GetActorRightVector allows us to move relative to the direction the actor is facing. Since the camera faces the same way as the actor, this ensures that our forward key is always forward relative to what the player sees.

使用GetActorForwardVector 和 GetActorRightVector 能使我们朝着面向的方向前后左右移动.由于相机的朝向和actor的方向一样,这将确保我们的前进键总是相对于玩家所看到的方向.

      1.We have finished coding. We can now compile our code and drag an instance of our new class from theContent Browser into the Level Editor window inside theUnreal Engine editor.

                我们已经编写好了代码,我们编译代码拖一个  实例 到游戏世界中  

Feel free to add aStatic Mesh or other visualComponent, or play without one. You should feel a smooth acceleration and deceleration to your camera's movement as it follows you around the level, but your rotation should feel tight and instantaneous. Try changing some of the properties on the SpringArmComponent to see how they affect the feel of your controls, such as adding "Camera Rotation Lag" or incresing or decreasing "Camera Lag".

我们可以任意添加静态模型或者可视的组件,或者啥都没开始拖动.你应该感相机到平稳加速和减速移动.但是你的旋转是立即的.尝试着修改SpringArmComponent 里面的属性,它们是如何影响你的感觉控制,比如增加"Camera Rotation Lag"或者增加或者减少"Camera Lag".

好了,尝试着拖动和旋转这个实例吧(非Play模式下)



Finished Code 完成代码

PawnWithCamera.h


// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.#pragma once#include "GameFramework/Pawn.h"#include "PawnWithCamera.generated.h"UCLASS()class HOWTO_PLAYERCAMERA_API APawnWithCamera : public APawn{    GENERATED_BODY()public:    // Sets default values for this pawn's properties    APawnWithCamera();    // 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;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

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.#include "HowTo_PlayerCamera.h"#include "PawnWithCamera.h"// Sets default valuesAPawnWithCamera::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->AttachTo(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->AttachTo(OurCameraSpringArm, USpringArmComponent::SocketName);    //Take control of the default Player    AutoPossessPlayer = EAutoReceiveInput::Player0;}// Called when the game starts or when spawnedvoid APawnWithCamera::BeginPlay(){    Super::BeginPlay();}// Called every framevoid 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.SafeNormal() * 100.0f;            FVector NewLocation = GetActorLocation();            NewLocation += GetActorForwardVector() * MovementInput.X * DeltaTime;            NewLocation += GetActorRightVector() * MovementInput.Y * DeltaTime;            SetActorLocation(NewLocation);        }    }}// Called to bind functionality to inputvoid APawnWithCamera::SetupPlayerInputComponent(class UInputComponent* InputComponent){    Super::SetupPlayerInputComponent(InputComponent);    //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 functionsvoid 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;}

    4.On Your Own! 自己动手做!

Using what you have learned, try to do the following:

  • Give the player a "run" key to hold down that will increase the Pawn's movement speed.

  • Experiment with different ways to mix automatic and input-driven camera movement. This is a very deep area of game development with a lot of room to explore!

  • Increase, decrease, or remove the lag from your Spring Component to get a better understanding of how much lag can affect your camera's overall feel.

  • Implement a small amount of periodic motion, possibly slightly randomized or using aCurve asset, to create a "handheld" feel to your camera.

  • Give your Camera some amount of automatic turning, so that the camera gradually gets behind the moving player object and faces the direction the player is moving.

As for the specifics covered in this tutorial:

  • For more information on Cameras and ways to control them, see theCamera framework page.

  • To learn more about Components, try the Components And Collision tutorial.

  • For further tutorials, see the C++ Programming Tutorials page.

-------------------------------------------------题目我整理好了发上----------------------------------------------------------------------------

5.Components And Collision 组件和碰撞





0 0
原创粉丝点击