最简单的 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 文件之前。


      #include "CoreMinimal.h"
      #include "GameFramework/Actor.h"
      // include before generated file
      #include "Components/BoxComponent.h"
      #include "OpenDoorWithLerp.generated.h"
  
 

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

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


      ...
      public:
     	// Called every frame
     	virtual void Tick(float DeltaTime) override;
     	UPROPERTY(EditAnywhere)
      	UStaticMeshComponent* Door;
     	UPROPERTY(EditAnywhere)
      	UBoxComponent* MyBoxComponent;
     	// declare overlap begin function
     	UFUNCTION()
     	void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
     	// declare overlap end function
     	UFUNCTION()
     	void OnOverlapEnd(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
     	bool Open;
     	float RotateValue;
      	FRotator DoorRotation;
  
 

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

#include "Kismet/KismetMathLibrary.h"
 

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


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

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


      void AOpenDoorWithLerp::Tick(float DeltaTime)
      {
      	Super::Tick(DeltaTime);
      	DoorRotation = Door->RelativeRotation;
         if(Open)
          {
              Door->SetRelativeRotation(FMath::Lerp(FQuat(DoorRotation), FQuat(FRotator(0.0f, RotateValue, 0.0f)), 0.01f));
          }
         else
          {
              Door->SetRelativeRotation(FMath::Lerp(FQuat(DoorRotation), FQuat(FRotator(0.0f, 0.0f, 0.0f)), 0.01f));
          }
      }
  
 

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

OnOnverlapEnd 简单地将 Open 设置为 false


      void AOpenDoorWithLerp::OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
      {
         if ( (OtherActor != nullptr ) && (OtherActor != this) && ( OtherComp != nullptr ) )
          {
              FVector PawnLocation = OtherActor->GetActorLocation();
              FVector Direction = GetActorLocation() - PawnLocation;
              Direction = UKismetMathLibrary::LessLess_VectorRotator(Direction, GetActorRotation());
             if(Direction.X > 0.0f)
              {
                  RotateValue = 90.0f;
              }
             else
              {
                  RotateValue = -90.0f;
              }
              Open = true;
          }
      }
      void AOpenDoorWithLerp::OnOverlapEnd(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
      {
         if ( (OtherActor != nullptr ) && (OtherActor != this) && ( OtherComp != nullptr ) )
          {
              Open = false;
          }
      }
  
 

我们已经完成了代码。进入编辑器并编译。将角色拖放到游戏世界中。将 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个月内不可修改。