最简单的 UE 4 C++ 教程 ——通过插值和重叠事件实现开门效果【三十一】

举报
ShaderJoy 发表于 2021/11/18 23:41:22 2021/11/18
【摘要】 效果图 原教程是基于 UE 4.18,我是基于 UE 4.25】 英文原地址 在本教程中,在这个虚幻引擎4 C++ 教程中,我们将学习如何依据玩家的方向,通过使用 lerp 函数和重叠事件自动打开一扇门。创建一个新的 actor 类,比如叫它 OpenDoorWithLerp 。 首先,...

效果图

原教程是基于 UE 4.18,我是基于 UE 4.25】

英文原地址

在本教程中,在这个虚幻引擎4 C++ 教程中,我们将学习如何依据玩家的方向,通过使用 lerp 函数和重叠事件自动打开一扇门。创建一个新的 actor 类,比如叫它 OpenDoorWithLerp 

首先,在 .h 文件中,让我们在文件的顶部使用 #include BoxComponent 。确保它出现在 Actor 的 generated.h 文件之前。


  
  1. #include "CoreMinimal.h"
  2. #include "GameFramework/Actor.h"
  3. // include before generated file
  4. #include "Components/BoxComponent.h"
  5. #include "OpenDoorWithLerp.generated.h"

接下来,我们将创建变量。我们将声明门 的 UStaticMeshComponentUBoxComponent、我们的重叠函数、boolfloat 和用于门旋转的 FRotator 变量。

三个 bool 变量确定门的状态,四个 float 变量为门设置不同的数字。接下来,我们将添加用于切换门的函数和使用构建门本身的 UStaticMeshComponentUBoxComponent。所有元素将放在头文件的公共部分之下。


  
  1. ...
  2. public:
  3. // Called every frame
  4. virtual void Tick(float DeltaTime) override;
  5. UPROPERTY(EditAnywhere)
  6. UStaticMeshComponent* Door;
  7. UPROPERTY(EditAnywhere)
  8. UBoxComponent* MyBoxComponent;
  9. // declare overlap begin function
  10. UFUNCTION()
  11. void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
  12. // declare overlap end function
  13. UFUNCTION()
  14. void OnOverlapEnd(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
  15. bool Open;
  16. float RotateValue;
  17. FRotator DoorRotation;

接下来,我们将进入 Actor 的 .cpp 文件。我们首先要 #include KismetMathLibrary 头文件。我们将在重叠函数中使用一个数学函数。

#include "Kismet/KismetMathLibrary.h"
 

在构造函数中,我们将设置默认变量。我们首先将门的 Open (bool 类型)设置为 false。接下来,我们将设置我们的 UBoxComponentUStaticMeshComponent 。我们将UBoxComponent 设置为我们的 RootComponent 。然后,将重叠函数连接到 UBoxComponent 。稍后,我们将创建它们正在调用的重叠函数。


  
  1. AOpenDoorWithLerp::AOpenDoorWithLerp()
  2. {
  3. // Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
  4. PrimaryActorTick.bCanEverTick = true;
  5. Open = false;
  6. MyBoxComponent = CreateDefaultSubobject<UBoxComponent>(TEXT("My Box Component"));
  7. MyBoxComponent->InitBoxExtent(FVector(50,50,50));
  8. RootComponent = MyBoxComponent;
  9. Door = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("My Mesh"));
  10. Door->SetRelativeLocation(FVector(0.0f, 50.0f, -50.0f));
  11. Door->SetupAttachment(RootComponent);
  12. MyBoxComponent->OnComponentBeginOverlap.AddDynamic(this, &AOpenDoorWithLerp::OnOverlapBegin);
  13. MyBoxComponent->OnComponentEndOverlap.AddDynamic(this, &AOpenDoorWithLerp::OnOverlapEnd);
  14. }

Tick 函数中,我们将检查门是否打开,并运行 lerp 函数。必须在 Tick 函数中运行一个 lerp 函数。我们将通过使用 Door->RelativeRotation 来获取门的旋转,以返回门在每一帧上的旋转。在得到门的旋转后,我们将平滑地移动 yaw 到 90,-90,或 0。


  
  1. void AOpenDoorWithLerp::Tick(float DeltaTime)
  2. {
  3. Super::Tick(DeltaTime);
  4. DoorRotation = Door->RelativeRotation;
  5. if(Open)
  6. {
  7. Door->SetRelativeRotation(FMath::Lerp(FQuat(DoorRotation), FQuat(FRotator(0.0f, RotateValue, 0.0f)), 0.01f));
  8. }
  9. else
  10. {
  11. Door->SetRelativeRotation(FMath::Lerp(FQuat(DoorRotation), FQuat(FRotator(0.0f, 0.0f, 0.0f)), 0.01f));
  12. }
  13. }

接下来,让我们创建重叠函数。OnOverlapBegin 将首先对空值进行条件检查,以确定函数是否应该继续。然后,该函数根据玩家和 actor 的位置和旋转来检查他们所面对的方向。在这个函数中,我们的玩家也就是我们的 Pawn 是传递给函数的 OtherActor 参数。我们用 Actor 的位置减去Pawn 的位置,得到一个方向 FVector。然后我们需要考虑父组件的旋转,因此我们运行UKismetMathLibrary::LessLess_VectorRotator。这个方法取自虚幻引擎4的内容示例。如果玩家在门前,则 RotateValue 将等于 90.0f,如果不是,则 RotateValue 将等于 -90.0f 。然后,最后我们将 Open 设为 true

OnOnverlapEnd 简单地将 Open 设置为 false


  
  1. void AOpenDoorWithLerp::OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
  2. {
  3. if ( (OtherActor != nullptr ) && (OtherActor != this) && ( OtherComp != nullptr ) )
  4. {
  5. FVector PawnLocation = OtherActor->GetActorLocation();
  6. FVector Direction = GetActorLocation() - PawnLocation;
  7. Direction = UKismetMathLibrary::LessLess_VectorRotator(Direction, GetActorRotation());
  8. if(Direction.X > 0.0f)
  9. {
  10. RotateValue = 90.0f;
  11. }
  12. else
  13. {
  14. RotateValue = -90.0f;
  15. }
  16. Open = true;
  17. }
  18. }
  19. void AOpenDoorWithLerp::OnOverlapEnd(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
  20. {
  21. if ( (OtherActor != nullptr ) && (OtherActor != this) && ( OtherComp != nullptr ) )
  22. {
  23. Open = false;
  24. }
  25. }

我们已经完成了代码。进入编辑器并编译。将角色拖放到游戏世界中。将 BoxComponent 的碰撞预设设置为 Trigger ,并从启动器内容中添加门静态网格作为 UStaticMeshComponent

那么就可以得到如文章开头那样的效果

文章来源: panda1234lee.blog.csdn.net,作者:panda1234lee,版权归原作者所有,如需转载,请联系作者。

原文链接:panda1234lee.blog.csdn.net/article/details/119295580

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。