UE4编程之C++创建一个FPS工程创建模式&角色&处理输入
Posted 晚起的蚂蚁
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UE4编程之C++创建一个FPS工程创建模式&角色&处理输入相关的知识,希望对你有一定的参考价值。
从今天开始,我们一起来学习一下,如何使用C++将一个不带有任何初学者内容的空模板,从无到有的创建一个简答却完整的FPS项目,通过这几篇文章的学习,我们大致了解到UE4 C++编程的流程,能够成功创建一个新的游戏模式,创建出第一人称的角色,他能够在场景中漫游并且向周围射击,完成一个整个工程。
第一部分:
(一)创建项目,新建游戏模式
1.新建一个C++的空项目,没有初学者内容,取名MyFPSProject。
2.点击创建后,将会在VS打开项目。首先我们来看一下VS的目录,系统自动帮我们建立了MyFPSProject的类和 MyFPSProjectGameMode的游戏模式类。等下我们会用到它。
如上图,点击运行,此时VS将会以调试的方式打开UE4编辑器,打开我们的工程,大概看一下内容浏览器,如果看过之前我的那翻译的那篇官方文档,就应该明白C++项目中,会有C++Classes,而之后我们创建的C++代码,都会出现在这里。
3.新建一个Maps文件夹,保存当前map为:MyFPSProjectMap
4.执行 编辑--项目设置:更改编辑器默认场景和游戏模式:分别为刚刚保存的MyFPSProjectMap,和之前在VS工程里面看到的引擎为我们创建的空的游戏模式MyFPSProjectGameMode。
5.然后简单介绍一下游戏模式,游戏模式包含了游戏本身的定义,包括游戏规则啊,胜利的条件等等,同时,他也指定了一些默认的游戏类(gameplay framework)类让我们使用,包含Pawn,PlayerController,和HUD。在我们创建我们的FPS角色之前,我们首先需要创建一个游戏模式引用角色。这里,我们只要在引擎为我们自动生成的游戏模式中添加内容即可。
为了保证游戏模式已经更换成我们自己的,我们先试着输出一个测试信息,打开VS工程中的MyFPSProjectGameMode.h,他默认应该是这样
- #pragma once
- #include "GameFramework/GameMode.h"
- #include "MyFPSProjectGameMode.generated.h"
- /**
- *
- */
- UCLASS()
- class MYFPSPROJECT_API AMyFPSProjectGameMode : public AGameMode
- {
- GENERATED_BOD
- };
大概看一下这段代码,有两处可能要稍微解释一下
1.代码里面两个宏命令,UCLASS和GENERATED_BOD,只要是我们使用UE4 的C++类向导添加的自定义类,它头上都会有UCLASS这个宏,他是为了让引擎知道他的存在,这样我们写的类就能被包含在序列化等等其他引擎功能中,同时,等下我们就会发现,在自定义类的头部有UFUNCTION()宏命令,也是同样的作用。对于properties 还有一个UPROPERTY宏,这些说明符可以再 ObjectBase.h找到。GENERATED_BOD这里先不做解释。
2.实际的游戏模式类名为“AMyFPSProjectGameMode”,前缀‘A‘表示这个类最终继承自Actor。这里在之前的那篇翻译的文章中也有提到。
6.接着,我们要重写一个函数 virtual void StartPlay() override:
MyFPSProjectGameMode.h
- #pragma once
- #include "GameFramework/GameMode.h"
- #include "MyFPSProjectGameMode.generated.h"
- /**
- *
- */
- UCLASS()
- class MYFPSPROJECT_API AMyFPSProjectGameMode : public AGameMode
- {
- GENERATED_BODY()
- virtual void StartPlay() override;
- };
- #include "MyFPSProject.h"
- #include "MyFPSProjectGameMode.h"
- #include "Engine.h"
- void AMyFPSProjectGameMode::StartPlay()
- {
- Super::BeginPlay();
- StartMatch();
- if (GEngine){
- GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, TEXT("HELLO WORLD"));
- }
- }
1.关闭编辑器
2.VS编译代码
3.重新VS F5调试打开编辑器
4.打开相应项目相应地图。
OK,以后只要在代码中增加了函数,就需要这样执行。
以上两个信息,分别说明了我们的游戏模式已经创建成功,并且正在运行。
(二)创建游戏角色,引用到游戏模式中
引擎有一个内置的类叫做DefaultPawn,他是一个Pawn物体,有一些简单的漫游的功能。我们希望创建一个类似人类走在地上的角色,因此我们需要创建自己的Pawn。引擎专门有这样一个类,名字叫做Character,它继承自Pawn,但是已经包含一些移动的功能了,比如走,跑,和跳。我们将使用Character类来作为我们FPS角色的父类。
1.在UE4中选择文件--添加代码到项目,父类选择Character,命名MyFPSCharacter。这里就用到之前说到的UE4的C++类向导了,官方这样描述:使用C++类向导添加类,也可是手动在VS里面添加.h .cpp文件来创建一个新的类。但是C++类向导填写标题和源模板建立虚幻的特定的宏,简化了工艺,所以推荐使用类向导。
接下来看一下引擎自动生成的代码:
MyFPSCharacter.h
- #pragma once
- #include "GameFramework/Character.h"
- #include "MyFPSCharacter.generated.h"
- UCLASS()
- class MYFPSPROJECT_API AMyFPSCharacter : public ACharacter
- {
- GENERATED_BODY()
- public:
- // Sets default values for this character‘s properties
- AMyFPSCharacter();
- // 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;
- };
- #include "MyFPSProject.h"
- #include "MyFPSCharacter.h"
- // 构造函数
- AMyFPSCharacter::AMyFPSCharacter()
- {
- // Set this character to call Tick() every frame. You can turn this off to improve performance if you don‘t need it.
- PrimaryActorTick.bCanEverTick = true;
- }
- // 当产生式会被调用
- void AMyFPSCharacter::BeginPlay()
- {
- Super::BeginPlay();
- }
- // 每一帧都会调用
- void AMyFPSCharacter::Tick( float DeltaTime )
- {
- Super::Tick( DeltaTime );
- }
- // 绑定用户输入
- void AMyFPSCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)
- {
- Super::SetupPlayerInputComponent(InputComponent);
- }
- // 当产生式会被调用
- void AMyFPSCharacter::BeginPlay()
- {
- Super::BeginPlay();
- if (GEngine){
- GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, TEXT("We are using FPSCharacter!"));
- }
- }
首先添加角色的头文件:
- #include "MyFPSCharacter.h"
- AMyFPSProjectGameMode::AMyFPSProjectGameMode(const class FPostConstructInitializeProperties& PCIP) : Super(PCIP)
- {
- DefaultPawnClass = AMyFPSCharacter::StaticClass();
- }
- #pragma once
- #include "GameFramework/GameMode.h"
- #include "MyFPSProjectGameMode.generated.h"
- /**
- *
- */
- UCLASS()
- class MYFPSPROJECT_API AMyFPSProjectGameMode : public AGameMode
- {
- GENERATED_UCLASS_BODY()
- virtual void StartPlay() override;
- };
(三)绑定输入,使得角色动起来!
首先我们绑定事件到WASD这几个键上。
1. 创建映射:编辑--项目设置
观察上图,就会发现这里有两种映射,一种是虚拟轴映射,一种是动作映射,其实和Unity一样,我也框出了二者的不同,我们的动作和摄像机的控制是使用的坐标轴映射,这样可以实现他们处理持续不间断输入功能,此外,动作映射为非连续性的事件处理输入信息,比如等下我们要添加的Jump跳跃的动作映射。
上面的填表很简单,具体步骤不做赘述,唯一一点要注意的是,两个相反的方向值为-1.
2.添加函数:我们要为角色添加连个函数:MoveFoward()和MoveRight()两个函数,来获取角色的方向,并在相应方向上添加位移。
MyFPSCharacter.h
- #pragma once
- #include "GameFramework/Character.h"
- #include "MyFPSCharacter.generated.h"
- UCLASS()
- class MYFPSPROJECT_API AMyFPSCharacter : public ACharacter
- {
- GENERATED_BODY()
- public:
- // Sets default values for this character‘s properties
- AMyFPSCharacter();
- // 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;
- UFUNCTION()
- void MoveForward(float Val);
- UFUNCTION()
- void MoveRight(float Val);
- };
- void AMyFPSCharacter::MoveForward(float Value)
- {
- if ((Controller != NULL) && (Value != 0.0f))
- {
- // 找到前进的方向
- FRotator Rotation = Controller->GetControlRotation();
- // 限制前进或者降落时的角度
- if (CharacterMovement->IsMovingOnGround() || CharacterMovement->IsFalling())
- {
- Rotation.Pitch = 0.0f;
- }
- // 添加位移
- FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::X);
- AddMovementInput(Direction, Value);
- }
- }
- void AMyFPSCharacter::MoveRight(float Value)
- {
- if ((Controller != NULL) && (Value != 0.0f))
- {
- // 找到前进的方向
- FRotator Rotation = Controller->GetControlRotation();
- const FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::Y);
- // 添加位移
- AddMovementInput(Direction, Value);
- }
- }
简单来说,就是都需要这么两步
(1)获取方向:先找到前进方向,然后对方向做处理
FRotator Rotation = Controller->GetControlRotation();
const FVector Direction = FRotationMatrix(Rotation).GetScaledAxis(EAxis::Y);
(2)在对应方向上添加位移:
AddMovementInput(Direction, Value);
3.绑定映射和函数。
接下来我们需要把刚刚创建好的映射和添加的函数绑定,很简单,只需要在角色的SetupPlayerInputComponent设置用户输入组件的函数里面添加两行即可。
- // 绑定用户输入
- void AMyFPSCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)
- {
- Super::SetupPlayerInputComponent(InputComponent);
- //轴名字,xx,函数名字
- InputComponent->BindAxis("MoveForward", this, &AMyFPSCharacter::MoveForward);
- InputComponent->BindAxis("MoveRight", this, &AMyFPSCharacter::MoveRight);
- }
5.继续处理输入,接下来,我们为鼠标创建映射,用鼠标的移动来控制视角,即控制摄像机的旋转。同样,还是上面的三步:
(1)创建映射,注意Y这里是-1
(2)添加函数,这里有一点要注意,Character 类已经为我们定义了两个非常重要的函数:AddYawInput()和AddPitchInput(),也就是说我们不用自己再添加了。如果我们想要添加更多功能,比如控制鼠标灵敏度或者坐标轴的倒置,我们需要在把他们传递给这两个函数之前,自己去写函数来调整他们的值。但是,在这个案例中,我们直接把我们的输入绑定给他们。好的,这一步跳过!
(3)绑定函数和映射
- // 绑定用户输入
- void AMyFPSCharacter::SetupPlayerInputComponent(class UInputComponent* InputComponent)
- {
- Super::SetupPlayerInputComponent(InputComponent);
- //轴名字,xx,函数名字
- InputComponent->BindAxis("MoveForward", this, &AMyFPSCharacter::MoveForward);
- InputComponent->BindAxis("MoveRight", this, &AMyFPSCharacter::MoveRight);
- InputComponent->BindAxis("Turn", this, &AMyFPSCharacter::AddControllerYawInput);
- InputComponent->BindAxis("LookUp", this, &AMyFPSCharacter::AddControllerPitchInput);
- }
右下角会有编译状态的提示。好的编译成功后,进入游戏测试,没问题!
6.再添加一个功能吧:角色可以跳跃!处理过程还是一样:
(1)添加映射
(2)添加函数
这里有一点要说明,不知道大家是否还记得之前的那篇翻译的官方文章,里面有提到Character类的优势,它里面其实已经为我们添加好了 一些函数,比如跳啊,走啊,跑啊之类, 查看Character.h文件,我们会发现里面内置了跳跃的函数,它绑定了bPressedJump 变量。所以我们 仅仅需要当跳跃事件被触发时设置标志位1,当跳跃键被释放时,设置为0.我们需要两个函数来实现这些。
- UFUNCTION()
- void OnStartJump();
- UFUNCTION()
- void OnStopJump();
- void AMyFPSCharacter::OnStartJump()
- {
- bPressedJump = true;
- }
- void AMyFPSCharacter::OnStopJump()
- {
- bPressedJump = false;
- }
- InputComponent->BindAction("Jump", IE_Pressed, this, &AMyFPSCharacter::OnStartJump);
- InputComponent->BindAction("Jump", IE_Released, this, &AMyFPSCharacter::OnStopJump);
(四)总结一下今天的内容
今天的内容就到这里,不急着更新,先一起总结一下今天做了哪些事情吧:
1.使用空模板,创建空白C++工程。
2.创建了一个简单的游戏模式,到目前为止这个游戏模式仅仅只完成了引用游戏角色的任务。
3.创建了一个简单的角色,他可以完成一些动作,但是还没有网格。这部分内容会在下一篇文章中说明。
4.处理了输入。输入处理很简单,就是简单的三步:
(1)创建映射
(2)创建函数
(3)绑定映射和函数
我们总共用UE4的类向导创建了两个类:MyFPSGameMode和MyFPSCharacter,这里还没有涉及到蓝图的内容,C++和蓝图将会在下一篇文章 中做总结,并且为角色添加网格等更多功能。
最后说明,博客的主人俺只是一个大三的学生,这些是我花费了自己大量的课余时间整理的,制作分享,不会考虑任何商业因素,如果大家喜欢,欢迎大家支持,如果文中有错误,还望大家指出,我们一同学习一同进步。如需转载,请注明作者,注明CSDN本文链接 http://blog.csdn.net/u011707076/article/details/44180951
以上是关于UE4编程之C++创建一个FPS工程创建模式&角色&处理输入的主要内容,如果未能解决你的问题,请参考以下文章