|
本文是《Unreal Engine 4 C++入门教程》的下半部分,上半部分请见 作者|Tommy Tran Feb 6 2018 | 翻译 开发游戏的老王 实现运动
我们并不是通过增加偏移量的方式实现运动,而是使用物理来实现!首先,我们需要一个变量来表示作用在球上力的大小。
回到Visual Studio并打开BasePlayer.h。在组件变量下面添加如下代码:
UPROPERTY(EditAnywhere, BlueprintReadWrite)
float MovementForce;
EditAnywhere允许我们在细节面板中编辑MovementForce,BlueprintReadWrite允许我们使用蓝图节点读写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);
上述代码将MoveUp和MoveRight与MoveUp() 和 MoveRight()绑定到了一起。
移动函数就完成了,接下来,我们要在网格组件上启用物理。
启用物理
将如下代码添加到ABasePlayer()中:
Mesh->SetSimulatePhysics(true);
MovementForce = 100000;
第一行允许物理作用力影响网格,第二行将MovementForce设为100000。这意味着,当球移动时,其上的作用力将有100000个单位。默认情况下,物理对象重量大约是110公斤,所以我们需要一个很大的力才能移动它们!
如果是先创建了子类,那么即使我们在基类里改变了一些属性的值,在子类中,它们也不会改变。本例中, BP_Player 的Simulate 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,然后收集一些金币,试一下新的实现。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|