您的位置:首页 > 产品设计 > UI/UE

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

2015-06-07 10:56 661 查看

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 包裹属性

上面这个介绍是我在/article/7023304.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是一个关键字声明,作用是使这个类只暴露指定函数给其它模块, 减少编译时间。

这些关键字声明都可以在/article/1656067.html这篇博客找到,往后翻还有其他宏的关键字介绍。

然后是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 interface

public:
/** 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到底是什么,可以在这里了解。/article/8205469.html

const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);这一段是生成一个旋转矩阵,然后取他X轴的向量,也就是面朝的方向的向量。

AddMovementInput(Direction, Value); 朝着面朝方向的向量,移动Value值的距离。

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

以上则是我对这个Third Person框架的理解,如有不正,欢迎指出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: