UE4官方Third Person框架初学者见解

来源:互联网 发布:生化危机知乎剧情 编辑:程序博客网 时间:2024/05/16 10:00

UE4官方Third Person框架初学者见解

以下是我作为一个UE4初学者在观看官方Third Person框架中对这个框架的理解和体会,如果有什么不正确的地方欢迎指正。

1.虚幻中的类前缀你会见到U,A,F,以下就是很好的罗列其中的意义

• U: UObject继承过来的,例如UTexture
• A: AActor继承过来的,例如AGameMode
• F: 其他的类和结构,例如FName, FVector
• T:模板,例如TArray,TMap,TQueue
• I: 接口类,ITransaction
• E:枚举, ESelectionMode
• B: Boolean, bEnabled

2.用宏定义来包裹C++代码
• UCLASS 来包裹类
• USTRUCT 包裹结构
• UFUNCTION 包裹功能
• UPROPERTY 包裹属性

上面这个介绍是我在http://www.cnblogs.com/NEOCSL/p/4059419.html这篇博客中看到的。

对于这两者,我的理解是:
前缀,是用来告诉我们在个类继承自哪里,我们只需要看类的前缀,我们就能知道这个类的父类是什么。

宏,这四个宏,他是UE4引擎用来区分我们自己本身的内部代码(不需要和引擎交互的部分)和需要和引擎蓝互的部分代码。如果你想要在引擎中调用某个C++类,那么你只需要在类前面加入UCLASS(),那么就可以在引擎中调用这个类,至于以下三个同理,如果你需要定义一个蓝图和C++互通的变量,那么你就需要使用UPROPERTY()来包裹他,在括号中可以声明一些属性来确定这些变量是否可以被访问等,这个在后面会提到。

然后我们看到生成这个Third Person游戏框架,他初始有两个类,一个是GameMode类,一个是Character类。

GameMode类,游戏模式,用于管理游戏的规则,以及玩家的生成也是在此类生成。

MyProjectGameMode.h

#pragma once#include "GameFramework/GameMode.h"#include "MyProjectGameMode.generated.h"UCLASS(minimalapi)class AMyProjectGameMode : public AGameMode{    GENERATED_BODY()public:    AMyProjectGameMode(const FObjectInitializer& ObjectInitializer);};

UCLASS(minimalapi),这段就是上面说的宏,用于包裹类,括号里面的minimalapi是一个关键字声明,作用是使这个类只暴露指定函数给其它模块, 减少编译时间。

这些关键字声明都可以在http://blog.csdn.net/xoyojank/article/details/43814839这篇博客找到,往后翻还有其他宏的关键字介绍。

然后是class AMyProjectGameMode : public AGameMode,这段的意思很明确,就是说明这个类继承自AgameMode类,前缀A表示继承自AActor。

GENERATED_BODY(),这是一个生成构造函数的宏,还有一些其他的定义,需要在类的最前方声明,与之相似的还有GENERATED_UCLASS_BODY(),只不过前者定义了构造函数,后者声明了却没有定义。

AMyProjectGameMode(const FObjectInitializer& ObjectInitializer);由于需要定义自己的构造函数,所以这里并没有使用GENERATED_BODY()定义的默认构造函数,而是重新声明了一个。

MyProjectGameMode.cpp

#include "MyProject.h"#include "MyProjectGameMode.h"#include "MyProjectCharacter.h"AMyProjectGameMode::AMyProjectGameMode(const FObjectInitializer& ObjectInitializer)    : Super(ObjectInitializer){    // set default pawn class to our Blueprinted character    static ConstructorHelpers::FClassFinder<APawn> PlayerPawnBPClass(TEXT("/Game/ThirdPerson/Blueprints/ThirdPersonCharacter"));    if (PlayerPawnBPClass.Class != NULL)    {        DefaultPawnClass = PlayerPawnBPClass.Class;    }}
AMyProjectGameMode::AMyProjectGameMode(const FObjectInitializer& ObjectInitializer)    : Super(ObjectInitializer)

这一段我也不甚理解,我猜测ObjectInitializer引用传递是这个类的父类引用,Super是一个变量,这里初始化为他的父类引用。

 static ConstructorHelpers::FClassFinder<APawn>PlayerPawnBPClass(TEXT("/Game/ThirdPerson/Blueprints/ThirdPersonCharacter"));

这一段代码作用于蓝图和C++的交互,从引擎读取ThirdPersonCharacter蓝图,保存在PlayerPawnBPClass中。

if (PlayerPawnBPClass.Class != NULL)    {        DefaultPawnClass = PlayerPawnBPClass.Class;    }

检测PlayerPawnBPClass是否读取成功,成功则设置为默认玩家角色。

MyProjectCharacter.h

// Copyright 1998-2015 Epic Games, Inc. All Rights Reserved.#pragma once#include "GameFramework/Character.h"#include "MyProjectCharacter.generated.h"UCLASS(config=Game)class AMyProjectCharacter : public ACharacter{    GENERATED_BODY()    /** Camera boom positioning the camera behind the character */    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))    class USpringArmComponent* CameraBoom;    /** Follow camera */    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))    class UCameraComponent* FollowCamera;public:    AMyProjectCharacter(const FObjectInitializer& ObjectInitializer);    /** Base turn rate, in deg/sec. Other scaling may affect final turn rate. */    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)    float BaseTurnRate;    /** Base look up/down rate, in deg/sec. Other scaling may affect final rate. */    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)    float BaseLookUpRate;protected:    /** Called for forwards/backward input */    void MoveForward(float Value);    /** Called for side to side input */    void MoveRight(float Value);    /**      * Called via input to turn at a given rate.      * @param Rate  This is a normalized rate, i.e. 1.0 means 100% of desired turn rate     */    void TurnAtRate(float Rate);    /**     * Called via input to turn look up/down at a given rate.      * @param Rate  This is a normalized rate, i.e. 1.0 means 100% of desired turn rate     */    void LookUpAtRate(float Rate);    /** Handler for when a touch input begins. */    void TouchStarted(ETouchIndex::Type FingerIndex, FVector Location);    /** Handler for when a touch input stops. */    void TouchStopped(ETouchIndex::Type FingerIndex, FVector Location);protected:    // APawn interface    virtual void SetupPlayerInputComponent(class UInputComponent* InputComponent) override;    // End of APawn interfacepublic:    /** Returns CameraBoom subobject **/    FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }    /** Returns FollowCamera subobject **/    FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; }};

开始的UCLASS(config=Game)和GENERATED_BODY()不再多言,前面提到过了,关键字也可以查。

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))    class USpringArmComponent* CameraBoom;

创建的是一个弹簧臂组件,用于放置摄像机。
UPROPERTY()上面提到过,里面设置的是属性,这个弹簧臂组件的属性,VisibleAnywhere(所有人可见),BlueprintReadOnly(蓝图只读),Category = Camera(分类设置为相机),meta = (AllowPrivateAccess = “true”)(允许访问私有类型)。依然可以在前面的博客上查到。

往后的也和前面大同小异,就不再多说了。

AMyProjectCharacter::AMyProjectCharacter(const FObjectInitializer& ObjectInitializer)    : Super(ObjectInitializer){    // Set size for collision capsule    GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);    // set our turn rates for input    BaseTurnRate = 45.f;    BaseLookUpRate = 45.f;    // Don't rotate when the controller rotates. Let that just affect the camera.    bUseControllerRotationPitch = false;    bUseControllerRotationYaw = false;    bUseControllerRotationRoll = false;    // Configure character movement    GetCharacterMovement()->bOrientRotationToMovement = true; // Character moves in the direction of input...       GetCharacterMovement()->RotationRate = FRotator(0.0f, 540.0f, 0.0f); // ...at this rotation rate    GetCharacterMovement()->JumpZVelocity = 600.f;    GetCharacterMovement()->AirControl = 0.2f;    // Create a camera boom (pulls in towards the player if there is a collision)    CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));    CameraBoom->AttachTo(RootComponent);    CameraBoom->TargetArmLength = 300.0f; // The camera follows at this distance behind the character       CameraBoom->bUsePawnControlRotation = true; // Rotate the arm based on the controller    // Create a follow camera    FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));    FollowCamera->AttachTo(CameraBoom, USpringArmComponent::SocketName); // Attach the camera to the end of the boom and let the boom adjust to match the controller orientation    FollowCamera->bUsePawnControlRotation = false; // Camera does not rotate relative to arm    // Note: The skeletal mesh and anim blueprint references on the Mesh component (inherited from Character)     // are set in the derived blueprint asset named MyCharacter (to avoid direct content references in C++)}

构造函数里设置的是一些角色属性,例如相机位置,跳跃高度等属性。后面这一段

 FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));    FollowCamera->AttachTo(CameraBoom, USpringArmComponent::SocketName); 

则是把相机附加到弹簧臂上。

void AMyProjectCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent){    // Set up gameplay key bindings    check(InputComponent);    InputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);    InputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);    InputComponent->BindAxis("MoveForward", this, &AMyProjectCharacter::MoveForward);    InputComponent->BindAxis("MoveRight", this, &AMyProjectCharacter::MoveRight);    // We have 2 versions of the rotation bindings to handle different kinds of devices differently    // "turn" handles devices that provide an absolute delta, such as a mouse.    // "turnrate" is for devices that we choose to treat as a rate of change, such as an analog joystick    InputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);    InputComponent->BindAxis("TurnRate", this, &AMyProjectCharacter::TurnAtRate);    InputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);    InputComponent->BindAxis("LookUpRate", this, &AMyProjectCharacter::LookUpAtRate);    // handle touch devices    InputComponent->BindTouch(IE_Pressed, this, &AMyProjectCharacter::TouchStarted);    InputComponent->BindTouch(IE_Released, this, &AMyProjectCharacter::TouchStopped);}

SetupPlayerInputComponent这个函数是设置输入组件的函数,在引擎中项目设置——输入里可以绑定输入动作和输入轴,然后在这个函数里和C++函数进行绑定。例如InputComponent->BindAction(“Jump”, IE_Pressed, this, &ACharacter::Jump); 就是绑定了一个名字为Jump的输入,IE_Pressed触发条件是压下设置好的那个按键,后面两个变量则捆绑在一起的,就是一个函数指针。同时Jump的函数,在ACharacter类中已经是自带有的,所以并不需要自己写,只需要调用即可。
鼠标移动改变视角亦是如此,只要把轴输出的值传递到AddControllerYawInput和AddControllerPitchInput即可。

TouchStarted和TouchStopped两个函数是触摸相关,这里不做解释。

最后则是MoveForward和MoveRight两个控制角色移动的函数。

void AMyProjectCharacter::MoveForward(float Value){    if ((Controller != NULL) && (Value != 0.0f))    {        // find out which way is forward        const FRotator Rotation = Controller->GetControlRotation();        const FRotator YawRotation(0, Rotation.Yaw, 0);        // get forward vector        const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);        AddMovementInput(Direction, Value);    }}void AMyProjectCharacter::MoveRight(float Value){    if ( (Controller != NULL) && (Value != 0.0f) )    {        // find out which way is right        const FRotator Rotation = Controller->GetControlRotation();        const FRotator YawRotation(0, Rotation.Yaw, 0);        // get right vector         const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);        // add movement in that direction        AddMovementInput(Direction, Value);    }}

const FRotator Rotation = Controller->GetControlRotation();取得当前角色旋转的角度。
const FRotator YawRotation(0, Rotation.Yaw, 0);把另外两个角度清空,只留下Yaw,也就是面向的角度。
至于Yaw到底是什么,可以在这里了解。http://blog.csdn.net/yuzhongchun/article/details/22749521
const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);这一段是生成一个旋转矩阵,然后取他X轴的向量,也就是面朝的方向的向量。
AddMovementInput(Direction, Value); 朝着面朝方向的向量,移动Value值的距离。

至于MoveRight同理,只是取的向量成了右侧的向量。

以上则是我对这个Third Person框架的理解,如有不正,欢迎指出。

0 0