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框架的理解,如有不正,欢迎指出。
相关文章推荐
- 每日一得-org.hibernate.hql.ast.QuerySyntaxException: Path expected for join!错误解决办法
- Ant入门基础
- iOSProgramming: The Big Nerd Ranch Guide (4th Edition) 阅读笔记-关于 View 的 Redrawing 和 Run Loop
- iOS开发零基础教程之UILabel的新初始化方法
- NGUI -- UICamera(监听输入事件,鼠标,键盘等)
- valueForKeyPath用途
- 重用系统自带UITableViewCell
- String、StringBuilder与StringBuffer的区别
- requireJS入门
- 安卓蓝牙开发中google例子BluetoothChat的问题
- 【Java GUI】标签、按钮和按钮事件
- UIView与subview之间事件响应链
- Ubuntu下用cue文件对ape和wav文件自动分轨
- Distinct Subsequences
- java.lang.NoClassDefFoundError: com/opensymphony/xwork2/util/finder/DefaultClassFinder$InfoBuildingV
- IOS开发学习笔记042-UITableView总结2
- 读AbstractQueuedSynchronizer类源码
- 在virtualbox上安装mac os mavericks遇到Missing Bluetooth Controller Transport问题解决办法
- #UITable代理#
- 代码创建UITableView