找回密码
 立即注册
查看: 311|回复: 0

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

[复制链接]
发表于 2021-8-11 23:17 | 显示全部楼层 |阅读模式
本文是《Unreal Engine 4 C++入门教程的下半部分,上半部分请见《Unreal Engine 4 C++入门教程(上)》
作者|Tommy Tran Feb 6 2018 | 翻译 开发游戏的老王
文章目录


      实现运动
        创建移动函数将轴映射和函数绑定启用物理创建跳跃函数在蓝图中重写函数
      收集金币
        实现重叠绑定重叠函数
      创建函数的默认实现
        创建蓝图实现



实现运动

我们并不是通过增加偏移量的方式实现运动,而是使用物理来实现!首先,我们需要一个变量来表示作用在球上力的大小。
回到Visual Studio并打开BasePlayer.h。在组件变量下面添加如下代码:
  1. UPROPERTY(EditAnywhere, BlueprintReadWrite)float MovementForce;
复制代码
EditAnywhere允许我们在细节面板中编辑MovementForce,BlueprintReadWrite允许我们使用蓝图节点读写MovementForce。
接下来,我们将创建两个函数。一个用于上下移动,另一个用于左右移动。
创建移动函数

在MovementForce的下面添加如下函数声明:
  1. voidMoveUp(float Value);voidMoveRight(float Value);
复制代码
后面,我们会将轴映射(Axis Mapping)绑定到这两个函数上,这样轴映射就会把scale值传进来(这就是为什么这俩函数需要float Value参数)。
注意:如果你不了解什么是轴映射scale,请参看本系列的蓝图教程。
现在,我们要实现这两个函数。打开BasePlayer.cpp并在最下面添加如下代码:
  1. void ABasePlayer::MoveUp(float Value){
  2.         FVector ForceToAdd =FVector(1,0,0)* MovementForce * Value;
  3.         Mesh->AddForce(ForceToAdd);}void ABasePlayer::MoveRight(float Value){
  4.         FVector ForceToAdd =FVector(0,1,0)* MovementForce * Value;
  5.         Mesh->AddForce(ForceToAdd);}
复制代码
MoveUp()将会在X-axis轴向为网格添加一个物理作用力,其大小就是MovementForce。通过它和Value相乘(Value就是轴的Scale),网格就可以在其正负方向上移动。
MoveRight()和MoveUp()的原理一样,只不过作用在Y-axis上。
现在,移动函数已经完成了,我们要把它们和轴映射绑定。
将轴映射和函数绑定

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


注意:因为我们会绑定轴映射和函数,因此它们的名字没必要相同。
在SetupPlayerInputComponent()中添加如下代码:
  1. InputComponent->BindAxis("MoveUp",this,&ABasePlayer::MoveUp);
  2. InputComponent->BindAxis("MoveRight",this,&ABasePlayer::MoveRight);
复制代码
上述代码将MoveUpMoveRight与MoveUp() 和 MoveRight()绑定到了一起。
移动函数就完成了,接下来,我们要在网格组件上启用物理。
启用物理

将如下代码添加到ABasePlayer()中:
  1. Mesh->SetSimulatePhysics(true);
  2. 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()下面添加如下代码:
  1. UPROPERTY(EditAnywhere, BlueprintReadWrite)float JumpImpulse;UFUNCTION(BlueprintImplementableEvent)voidJump();
复制代码
第一个变量叫JumpImpulse。我们将使用它实现跳跃。用EditAnywhere使它在编辑器中可编辑。使用BlueprintReadWrite使它可以被蓝图节点读写。
接下来是跳跃函数,UFUNCTION()会使Jump()对反射系统可见。BlueprintImplementableEvent会允许蓝图实现Jump()。如果蓝图没实现Jump(),那么当调用Jump()时,什么也不会发生。
注意: 如果你想用C++为它提供一个默认实现,请使用BlueprintNativeEvent取而代之。我们将在本教程的后面学习该技巧。
应为Jump是一个事件映射(action mapping),它的绑定方式略有不同。关闭BasePlayer.h 并打开BasePlayer.cpp。在SetupPlayerInputComponent()中添加如下代码:
  1. 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事件。这个事件要求函数有如下函数签名:
  1. FunctionName(AActor* OverlappedActor, AActor* OtherActor)
复制代码
回到Visual Studio并打开BaseCoin.h,在PlayCustomDeath()下面添加添加如下代码:
  1. UFUNCTION()voidOnOverlap(AActor* OverlappedActor, AActor* OtherActor);
复制代码
绑定以后,当金币碰到其它角色时将会执行OnOverlap(),此时OverlappedActor就是金币而OtherActor就是其它角色。
接下来,我们来实现OnOverlap()。
实现重叠

打开BaseCoin.cpp并在末尾添加如下代码:
  1. void ABaseCoin::OnOverlap(AActor* OverlappedActor, AActor* OtherActor){}
复制代码
因为我们只想检测金币和角色的重叠,我们需要将OtherActor显式类型转换为ABasePlayer。在转换之前,我们要先包含ABasePlayer的头文件。在#include "BaseCoin.h"下面添加如下代码:
  1. #include"BasePlayer.h"
复制代码
现在我们来进行转换,在虚幻引擎中,我们可以用如下方式转换:
  1. Cast<TypeToCastTo>(ObjectToCast);
复制代码
如果转换成功,那么将会返回ObjectToCast的指针,如果失败则会返回nullptr。通过检查结果是否为nullptr,我们可以判断对象是否为正确的类型。
在OnOverlap()中添加如下代码:
  1. if(Cast<ABasePlayer>(OtherActor)!=nullptr){Destroy();}
复制代码
现在,如果OnOverlap()执行,那么它将检查OtherActor是否为ABasePlayer类型。如果是,则销毁金币。
接下来,我们要绑定OnOverlap()。
绑定重叠函数

要把一个函数绑定到重叠事件,我们要使用事件的AddDynamic()方法。在ABaseCoin()中添加如下代码:
  1. OnActorBeginOverlap.AddDynamic(this,&ABaseCoin::OnOverlap);
复制代码
上述代码将把OnOverlap()绑定到OnActorBeginOverlap事件。当这个角色和其它角色发生重叠时,将触发这个事件。
编译并回到引擎。按下Play并开始收集金币。当角色和金币重叠,金币将把自己销毁,这样就消失了。


注意: 如果金币不消失,请尝试重启编辑器,让它来个全面的重编译。有些代码需要重启后才能正常工作。
在下面的部分,我们将实现另一个可重写的C++函数。然而,这次我们还要创建一个默认实现。我们将用OnOverlap()来介绍这个技巧。
创建函数的默认实现

要创建一个带默认实现的函数,我们需要使用BlueprintNativeEvent分类符。回到Visual Studio并打开 BaseCoin.h。在OnOverlap()的UFUNCTION()中添加BlueprintNativeEvent:
  1. UFUNCTION(BlueprintNativeEvent)voidOnOverlap(AActor* OverlappedActor, AActor* OtherActor);
复制代码
要使函数成为默认实现,我们需要添加_Implementation后缀。打开BaseCoin.cpp并将OnOverlap改为OnOverlap_Implementation:
  1. void ABaseCoin::OnOverlap_Implementation(AActor* OverlappedActor, AActor* OtherActor)
复制代码
这样,如果蓝图没有实现OnOverlap(),那么就会默认使用上面的函数。
接下来在BP_Coin中实现OnOverlap()函数。
创建蓝图实现

在蓝图实现中,我们将使用PlayCustomDeath()。这个C++函数将会加快金币的旋转速率。0.5秒钟后,硬币将自身销毁。
我们使用BlueprintCallable分类符让一个C++函数能够在蓝图中被调用。关闭BaseCoin.cpp并打开BaseCoin.h。在PlayCustomDeath()上面添加如下代码:
  1. UFUNCTION(BlueprintCallable)
复制代码
编译并关闭Visual Studio。回到引擎打开BP_Coin。重写On Overlap并创建如下连接:


这样,只要角色碰到金币,Play Custom Death就会执行。
点击编译并关闭BP_Coin。按下Play,然后收集一些金币,试一下新的实现。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Unity开发者联盟 ( 粤ICP备20003399号 )

GMT+8, 2024-11-24 06:22 , Processed in 0.093892 second(s), 26 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表