【UE4 C++】实现自动门

前言

本文章将会教你用C++如何实现自动门。
我们任务踩到开关上面门就会升起来,我们离开门之后,两秒后门会降下来。
在这里插入图片描述
在这里插入图片描述
2S后才会下落
在这里插入图片描述

创建C++文件

右键创建C++文件,继承Actor类。

.h文件内容

<声明门和开关的静态网格体>
静态网格体在哪里都可以看到,并且在蓝图中可以读写。

UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
	class UStaticMeshComponent* FloorSwitch;
UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
	class UStaticMeshComponent* Door;

<声明触发开关的感应器>
盒子组件在哪里都可以看到,并且在蓝图中可以读写。

UPROPERTY(VisibleAnywhere, BlueprintReadWrite)
		class UBoxComponent* TriggerBox;

<声明储存初始位置的变量>
有了门和开关的初始位置,之后确定门移动到什么位置就很好计算。

UPROPERTY(BlueprintReadWrite)
		FVector InitialDoorLocation; // 储存门的初始位置
UPROPERTY(BlueprintReadWrite) 
	FVector InitialSwitchLocation; // 储存开关的初始位置

<声明组件重合的触发反应的函数>
我们人物触碰到开关后做出的反应的实现就在这两个函数之中,一个是开始重叠的时候,一个是重叠结束的时候。

UFUNCTION()
		void OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor,  UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);

UFUNCTION()
	void OnOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);

这个函数这样声明不是凭空得出来的,因为我们要和我们的开关组件联系起来,那么联系起来的函数是有规定的。

首先我们看如何将他们联系起来:

TriggerBox->OnComponentBeginOverlap.AddDynamic(this, &AAFloorSwitch::OnOverlapBegin);
TriggerBox->OnComponentEndOverlap.AddDynamic(this, &AAFloorSwitch::OnOverlapEnd);

他们之间的联系就需要用上面这个来搭建联系,
我们点进去查看他的实现:

UPROPERTY(BlueprintAssignable, Category="Collision")
	FComponentBeginOverlapSignature OnComponentBeginOverlap;

我们看到他前面有一段声明,应该是他的类型声明吧?
我们找到他:
DECLARE_DYNAMIC_MULTICAST_SPARSE_DELEGATE_SixParams( FComponentBeginOverlapSignature, UPrimitiveComponent, OnComponentBeginOverlap, UPrimitiveComponent*, OverlappedComponent, AActor*, OtherActor, UPrimitiveComponent*, OtherComp, int32, OtherBodyIndex, bool, bFromSweep, const FHitResult &, SweepResult);
特别长,其实看不太懂,只知到这个函数的第一个和第三个对应着我们刚刚看到那个变量?,从第四个开始到后面的所有就是我们函数构建要填写的数据类型和名字,(数据类型和变量名之间的逗号要记得去掉。)
重叠结束函数也类似。

<声明存储时间变量>
FTimerHandle TimerHandle; 这里出现了一个新东西,FTimerHandle感觉就是储存某个实例运行对应时间的一个变量。

<声明离开之后关门时间变量>

UPROPERTY(EditAnywhere, BlueprintReadWrite)
	float SwitchTime;

<声明关门函数>

UFUNCTION()
	void CloseDoor();

<声明门的开关操作实现函数>
这个函数和我们之前见到的不一样,因为他的属性标签是BlueprintImplementableEvent,这个的意思就是这个函数在C++中声明,蓝图中实现,待会我们会知道如何去实现这个函数。

UFUNCTION(BlueprintImplementableEvent) // 蓝图实现函数
	void RaiseDoor(); // 门上升函数

UFUNCTION(BlueprintImplementableEvent)
	void LowerDoor();// 门下降函数

UFUNCTION(BlueprintImplementableEvent)
	void RaiseFloorSwitch(); // 开关上升

UFUNCTION(BlueprintImplementableEvent)
	void LowerFloorSwitch(); // 开关下降

<声明更新函数>

UFUNCTION(BlueprintCallable)
	void UpdateDoorLocation(float Z);

UFUNCTION(BlueprintCallable)
	void UpdateSwitchLocation(float Z);

.cpp 文件实现

<构造函数>

  • TriggerBox的初始化

创建实例,并且设他为根组件

TriggerBox = CreateDefaultSubobject<UBoxComponent>(TEXT("TriggerBox"));
RootComponent = TriggerBox;

设置开关盒子的碰撞类型:

它有四种类型:
NoCollision 无碰撞
QueryOnly 仅响应踪迹碰撞,无物理碰撞
PhysicsOnly 仅响应物理碰撞,无踪迹碰撞
QueryAndPhysics 同时响应物理碰撞和踪迹碰撞

在因为我们是站在开关上面,需要他做出一些其他的反应,而不是阻挡,所以我们选第二种是最合适的。
TriggerBox->SetCollisionEnabled(ECollisionEnabled::QueryOnly);

接下来设置的就是下图所展示的部分,
设置当前Mesh的对象类型(用于区别场景的Mesh类型,以便进行不同的碰撞响应)。
TriggerBox->SetCollisionObjectType(ECollisionChannel::ECC_WorldStatic);

我们只需要对人物做出反应,其他的不用考虑,所以先将所有通道都设置为忽略状态,再单独设置响应pawn类的重叠。

TriggerBox->SetCollisionResponseToAllChannels(ECollisionResponse::ECR_Ignore);
TriggerBox->SetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn, ECollisionResponse::ECR_Overlap); 

在这里插入图片描述
设置盒子的大小:TriggerBox->SetBoxExtent(FVector(64, 64, 32));

  • 门开关的初始化
    创建门开关的实例,附在根组件上。
FloorSwitch = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("FloorSwitch"));
FloorSwitch->SetupAttachment(RootComponent);
  • 门的初始化

创建门的实例,附在根组件上。

Door = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Door"));
Door->SetupAttachment(RootComponent);
  • 设置人离开开关后们停留的时间

SwitchTime = 2;

<BeginPlay()>
获得门和门开关的初始位置

InitialDoorLocation = Door->GetComponentLocation();
InitialSwitchLocation = FloorSwitch->GetComponentLocation();

将开关盒子与角色的重叠情况进行绑定

TriggerBox->OnComponentBeginOverlap.AddDynamic(this, &AAFloorSwitch::OnOverlapBegin);
TriggerBox->OnComponentEndOverlap.AddDynamic(this, &AAFloorSwitch::OnOverlapEnd);

<OnOverlapBegin自定义函数实现>
在开始重叠的时候,我们要把我们的时间手柄置为空,让门升起来,开关降下去。

GetWorldTimerManager().ClearTimer(TimerHandle);
RaiseDoor();
LowerFloorSwitch();

<OnOverlapEnd自定义函数实现>
GetWorldTimerManager().SetTimer(TimerHandle, this, &AAFloorSwitch::CloseDoor, SwitchTime);
设置时间,SwitchTime秒后执行关门操作。

<CloseDoor函数实现>
门降下去,开关升起来。

LowerDoor();
RaiseFloorSwitch();

<UpdateDoorLocation函数实现>
更新门的位置

FVector NewLocation = InitialDoorLocation;
NewLocation.Z += Z;
Door->SetWorldLocation(NewLocation);

<UpdateSwitchLocation更新门开关的位置>

FVector NewLocation = InitialSwitchLocation;
NewLocation.Z += Z;
FloorSwitch->SetWorldLocation(NewLocation);

创建蓝图

右键我们刚创建的C++类,创建蓝图。
给我们的组件挑选Mesh:
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
要在UE4中使用C++实现TexturerRenderTargetCube读取照片,你需要完成以下步骤: 1. 导入照片:在UE4编辑器中,右键单击Content Browser面板,选择Import选项,然后选择你想要导入的照片。 2. 创建TexturerRenderTargetCube:在你的UE4项目中,找到你想要添加TexturerRenderTargetCube的地方。然后在该位置创建一个TexturerRenderTargetCube对象。 3. 设置TexturerRenderTargetCube属性:在代码中设置你的TexturerRenderTargetCube对象的属性。为了从照片中创建立方体贴图,你需要设置RenderTarget的尺寸以及Texture的格式。 4. 从照片中创建立方体贴图:使用你导入的照片创建立方体贴图。你需要将照片分解为6个面,并将它们作为6个2D纹理分别应用到RenderTargetCube的6个面上。 5. 使用TexturerRenderTargetCube:将TexturerRenderTargetCube用于你的场景或材质中。你可以将它作为材质的纹理或将它用于场景中的天空盒。 下面是一些示例代码来实现这些步骤: ```cpp // 导入照片 UTexture2D* PhotoTexture = LoadObject<UTexture2D>(nullptr, TEXT("/Game/Textures/PhotoTexture.PhotoTexture")); // 创建TexturerRenderTargetCube UTextureRenderTargetCube* CubeRenderTarget = NewObject<UTextureRenderTargetCube>(); CubeRenderTarget->InitAutoFormat(256); // 设置TexturerRenderTargetCube属性 CubeRenderTarget->ClearColor = FLinearColor::Black; // 从照片中创建立方体贴图 int32 CubeFaceSize = CubeRenderTarget->SizeX / 4; for (int32 CubeFaceIndex = 0; CubeFaceIndex < 6; ++CubeFaceIndex) { // 创建一个2D纹理 UTexture2D* CubeFaceTexture = NewObject<UTexture2D>(); CubeFaceTexture->Source.Init(CubeFaceSize, CubeFaceSize, 1, 1, ETextureSourceFormat::TSF_BGRA8, &(PhotoTexture->PlatformData->Mips[0].BulkData)); // 应用2D纹理到RenderTargetCube CubeRenderTarget->GameThread_SetTextureCubeFace((ECubeFace)CubeFaceIndex, CubeFaceTexture, false, false); } // 使用TexturerRenderTargetCube UMaterialInstanceDynamic* DynamicMaterial = UMaterialInstanceDynamic::Create(Material, InWorld); DynamicMaterial->SetTextureParameterValue(TEXT("CubeTexture"), CubeRenderTarget); ``` 这样,你就可以使用C++实现TexturerRenderTargetCube读取照片了。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值