【新手必读】Unreal Engine 4 C++入门教程(下)

本文详细介绍了如何在Unreal Engine 4中使用C++实现角色移动、物理绑定和跳跃功能,包括轴映射、蓝图重写和金币碰撞处理。通过实际操作演示了如何在C++和蓝图中创建和绑定事件,提升游戏开发效率。
摘要由CSDN通过智能技术生成

本文是《Unreal Engine 4 C++入门教程的下半部分,上半部分请见《Unreal Engine 4 C++入门教程(上)》
作者|Tommy Tran Feb 6 2018 | 翻译 开发游戏的老王

实现运动

我们并不是通过增加偏移量的方式实现运动,而是使用物理来实现!首先,我们需要一个变量来表示作用在球上力的大小。

回到Visual Studio并打开BasePlayer.h。在组件变量下面添加如下代码:

UPROPERTY(EditAnywhere, BlueprintReadWrite)
float MovementForce;

EditAnywhere允许我们在细节面板中编辑MovementForceBlueprintReadWrite允许我们使用蓝图节点读写MovementForce

接下来,我们将创建两个函数。一个用于上下移动,另一个用于左右移动。

创建移动函数

MovementForce的下面添加如下函数声明:

void MoveUp(float Value);
void MoveRight(float Value);

后面,我们会将轴映射(Axis Mapping)绑定到这两个函数上,这样轴映射就会把scale值传进来(这就是为什么这俩函数需要float Value参数)。

注意:如果你不了解什么是轴映射scale,请参看本系列的蓝图教程。

现在,我们要实现这两个函数。打开BasePlayer.cpp并在最下面添加如下代码:

void ABasePlayer::MoveUp(float Value)
{
	FVector ForceToAdd = FVector(1, 0, 0) * MovementForce * Value;
	Mesh->AddForce(ForceToAdd);
}

void ABasePlayer::MoveRight(float Value)
{
	FVector ForceToAdd = FVector(0, 1, 0) * MovementForce * Value;
	Mesh->AddForce(ForceToAdd);
}

MoveUp()将会在X-axis轴向为网格添加一个物理作用力,其大小就是MovementForce。通过它和Value相乘(Value就是轴的Scale),网格就可以在其正负方向上移动。

MoveRight()MoveUp()的原理一样,只不过作用在Y-axis上。

现在,移动函数已经完成了,我们要把它们和轴映射绑定。

将轴映射和函数绑定

简单起见,笔者已经创建了轴映射。我们可以在Project Settings下的Input找到它们。

在这里插入图片描述

注意:因为我们会绑定轴映射和函数,因此它们的名字没必要相同。

SetupPlayerInputComponent()中添加如下代码:

InputComponent->BindAxis("MoveUp", this, &ABasePlayer::MoveUp);
InputComponent->BindAxis("MoveRight", this, &ABasePlayer::MoveRight);

上述代码将MoveUpMoveRightMoveUp()MoveRight()绑定到了一起。

移动函数就完成了,接下来,我们要在网格组件上启用物理。

启用物理

将如下代码添加到ABasePlayer()中:

Mesh->SetSimulatePhysics(true);
MovementForce = 100000;

第一行允许物理作用力影响网格,第二行将MovementForce设为100000。这意味着,当球移动时,其上的作用力将有100000个单位。默认情况下,物理对象重量大约是110公斤,所以我们需要一个很大的力才能移动它们!

如果是先创建了子类,那么即使我们在基类里改变了一些属性的值,在子类中,它们也不会改变。本例中, BP_PlayerSimulate Physics属性还没有开启。而如果现在再创建新的子类,它们的Simulate Physics属性就会默认被开启。

编译一下并回到引擎。打开BP_Player并选择网格组件,然后开启它的Simulate Physics

在这里插入图片描述

点击编译然后按下Play。使用W, A, S,D来控制球的移动。

在这里插入图片描述

接下来,我们将声明一个C++函数并使用蓝图来实现它。这将允许策划在不触碰C++的情况下实现功能。我们就以跳跃函数为例,学习这个技巧。

创建跳跃函数

首先,我们要将跳跃事件绑定到一个函数。本教程中我们使用空格键来控制跳跃。

在这里插入图片描述

回到Visual Studio并打开BasePlayer.h,在MoveRight()下面添加如下代码:

UPROPERTY(EditAnywhere, BlueprintReadWrite)
float JumpImpulse;

UFUNCTION(BlueprintImplementableEvent)
void Jump();

第一个变量叫JumpImpulse。我们将使用它实现跳跃。用EditAnywhere使它在编辑器中可编辑。使用BlueprintReadWrite使它可以被蓝图节点读写。

接下来是跳跃函数,UFUNCTION()会使Jump()对反射系统可见。BlueprintImplementableEvent会允许蓝图实现Jump()。如果蓝图没实现Jump(),那么当调用Jump()时,什么也不会发生。

注意: 如果你想用C++为它提供一个默认实现,请使用BlueprintNativeEvent取而代之。我们将在本教程的后面学习该技巧。

应为Jump是一个事件映射(action mapping),它的绑定方式略有不同。关闭BasePlayer.h 并打开BasePlayer.cpp。在SetupPlayerInputComponent()中添加如下代码:

InputComponent->BindAction("Jump", IE_Pressed, this, &ABasePlayer::Jump);

这样Jump就被绑定到Jump()上了。只有当我们按下Jump时,函数才会执行,如果你想让函数在Jump被释放时执行,那么请使用IE_Released

接下来,我们在蓝图中重写Jump()

在蓝图中重写函数

编译并关闭BasePlayer.cpp。然后,回到引擎并打开BP_Player。在蓝图面板上,将鼠标悬停在Functions那里,这时Override的下拉菜单会显示出来。点击并选择Jump。这样就会创建一个Event Jump事件。

注意: 如果C++函数没有返回值,那么会创建一个事件,如果有返回值,则会创建一个函数。

接下来,创建如下节点:

在这里插入图片描述

上述节点会在Z轴向对网格产生一个冲量(JumpImpulse)。注意,在当前实现方式中,角色可以无限跳跃。

接下来,我们要设置JumpImpulse。在工具栏中点击Class Defaults 并在细节面板中将JumpImpulse设为100000

在这里插入图片描述

点击编译并关闭BP_Player。按下Play,然后使用空格键跳跳试试。

在这里插入图片描述

在下个部分中,我们将实现当金币碰到角色时就消失。

收集金币

要处理重叠,我们需要为重叠事件(overlap event)绑定一个函数。这个函数必须满足两个条件。首先,这个函数必须有UFUNCTION()宏。另外,这个函数必须有正确的函数签名。本教程中,我们使用OnActorBeginOverlap事件。这个事件要求函数有如下函数签名:

FunctionName(AActor* OverlappedActor, AActor* OtherActor)

回到Visual Studio并打开BaseCoin.h,在PlayCustomDeath()下面添加添加如下代码:

UFUNCTION()
void OnOverlap(AActor* OverlappedActor, AActor* OtherActor);

绑定以后,当金币碰到其它角色时将会执行OnOverlap(),此时OverlappedActor就是金币而OtherActor就是其它角色。

接下来,我们来实现OnOverlap()

实现重叠

打开BaseCoin.cpp并在末尾添加如下代码:

void ABaseCoin::OnOverlap(AActor* OverlappedActor, AActor* OtherActor)
{
}

因为我们只想检测金币和角色的重叠,我们需要将OtherActor显式类型转换为ABasePlayer。在转换之前,我们要先包含ABasePlayer的头文件。在#include "BaseCoin.h"下面添加如下代码:

#include "BasePlayer.h"

现在我们来进行转换,在虚幻引擎中,我们可以用如下方式转换:

Cast<TypeToCastTo>(ObjectToCast);

如果转换成功,那么将会返回ObjectToCast的指针,如果失败则会返回nullptr。通过检查结果是否为nullptr,我们可以判断对象是否为正确的类型。

OnOverlap()中添加如下代码:

if (Cast<ABasePlayer>(OtherActor) != nullptr)
{
	Destroy();
}

现在,如果OnOverlap()执行,那么它将检查OtherActor是否为ABasePlayer类型。如果是,则销毁金币。

接下来,我们要绑定OnOverlap()

绑定重叠函数

要把一个函数绑定到重叠事件,我们要使用事件的AddDynamic()方法。在ABaseCoin()中添加如下代码:

OnActorBeginOverlap.AddDynamic(this, &ABaseCoin::OnOverlap);

上述代码将把OnOverlap()绑定到OnActorBeginOverlap事件。当这个角色和其它角色发生重叠时,将触发这个事件。

编译并回到引擎。按下Play并开始收集金币。当角色和金币重叠,金币将把自己销毁,这样就消失了。

在这里插入图片描述

注意: 如果金币不消失,请尝试重启编辑器,让它来个全面的重编译。有些代码需要重启后才能正常工作。

在下面的部分,我们将实现另一个可重写的C++函数。然而,这次我们还要创建一个默认实现。我们将用OnOverlap()来介绍这个技巧。

创建函数的默认实现

要创建一个带默认实现的函数,我们需要使用BlueprintNativeEvent分类符。回到Visual Studio并打开 BaseCoin.h。在OnOverlap()UFUNCTION()中添加BlueprintNativeEvent

UFUNCTION(BlueprintNativeEvent)
void OnOverlap(AActor* OverlappedActor, AActor* OtherActor);

要使函数成为默认实现,我们需要添加_Implementation后缀。打开BaseCoin.cpp并将OnOverlap改为OnOverlap_Implementation

void ABaseCoin::OnOverlap_Implementation(AActor* OverlappedActor, AActor* OtherActor)

这样,如果蓝图没有实现OnOverlap(),那么就会默认使用上面的函数。

接下来在BP_Coin中实现OnOverlap()函数。

创建蓝图实现

在蓝图实现中,我们将使用PlayCustomDeath()。这个C++函数将会加快金币的旋转速率。0.5秒钟后,硬币将自身销毁。

我们使用BlueprintCallable分类符让一个C++函数能够在蓝图中被调用。关闭BaseCoin.cpp并打开BaseCoin.h。在PlayCustomDeath()上面添加如下代码:

UFUNCTION(BlueprintCallable)

编译并关闭Visual Studio。回到引擎打开BP_Coin。重写On Overlap并创建如下连接:

在这里插入图片描述

这样,只要角色碰到金币,Play Custom Death就会执行。

点击编译并关闭BP_Coin。按下Play,然后收集一些金币,试一下新的实现。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值