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

Posted panda1234lee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最简单的 UE 4 C++ 教程 ——通过插值和重叠事件实现开门效果三十一相关的知识,希望对你有一定的参考价值。

效果图

原教程是基于 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

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

以上是关于最简单的 UE 4 C++ 教程 ——通过插值和重叠事件实现开门效果三十一的主要内容,如果未能解决你的问题,请参考以下文章

最简单的 UE 4 C++ 教程 —— 绘制 UE4 辅助调试的形状

最简单的 UE 4 C++ 教程 —— 寻找玩家的当前位置

最简单的 UE 4 C++ 教程 —— 漂浮的 Actor二十七

最简单的 UE 4 C++ 教程 —— 为 Charactor 添加重叠事件十九

最简单的 UE 4 C++ 教程 ——触发改变网格的材质三十

最简单的 UE 4 C++ 教程 ——两个相机视图的切换二十八