UE4 C++:事件绑定(输入、碰撞检测、定时器)

 目录

Input输入事件绑定

轴映射与动作映射:SetupPlayerInputComponent

编辑器设置对应名称、代码设置响应事件,实现具体动作

C++设置添加轴和动作映射

碰撞检测事件绑定

碰撞对象通道与预设

碰撞响应设置:是否模拟物理碰撞以及触发Overlap事件

碰撞响应类型:Blokc、Overlap、Ignore

C++实现

定时器Timer与事件绑定

设置定时器:SetTimer

清空定时器:ClearTimer

暂停和恢复:PauseTimer和UnPauseTimer

判断是否活跃且未暂停:IsTimerActive

获取定时器速率:GetTImerRate

获取经过时间和剩余时间:GetTimerElapsed & GetTimerRemaining


虚幻引擎中的碰撞响应参考 | 虚幻引擎5.0文档 (unrealengine.com)

变量、定时器和事件 | 虚幻引擎5.0文档 (unrealengine.com) 

 虚幻引擎中的Gameplay定时器 | 虚幻引擎5.0文档 (unrealengine.com)

Input输入事件绑定

轴映射与动作映射:SetupPlayerInputComponent

编辑器设置对应名称、代码设置响应事件,实现具体动作

绑定名称及事件,Action还需绑定按键 

void AMyCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

	PlayerInputComponent->BindAction("DropItem", EInputEvent::IE_Pressed, this, &AMyCharacter::DropItem);
	PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &AMyCharacter::Jump);
	PlayerInputComponent->BindAxis("MoveForward", this, &AMyCharacter::MoveForward);
	PlayerInputComponent->BindAxis("MoveRight", this, &AMyCharacter::MoveRight);
	PlayerInputComponent->BindAxis("PitchCamera", this, &AMyCharacter::PitchCamera);
	PlayerInputComponent->BindAxis("YawCamera", this, &AMyCharacter::YawCamera);
}

事件:

void AMyCharacter::MoveForward(float AxisValue)
{
	MovementInput.X = FMath::Clamp<float>(AxisValue, -1.f, 1.f);
}

void AMyCharacter::MoveRight(float AxisValue)
{
	MovementInput.Y = FMath::Clamp<float>(AxisValue, -1.f, 1.f);
}

void AMyCharacter::PitchCamera(float AxisValue)
{
	CameraInput.Y = AxisValue;
}

void AMyCharacter::YawCamera(float AxisValue)
{
	CameraInput.X = AxisValue;
}

设置按键,游戏暂停可以继续响应

InputComponent->BindAction("ESCEvent", IE_Pressed, this, &ASLAiPlayerController::ESCEvent).bExecuteWhenPaused=true;//游戏暂停可以执行

C++设置添加轴和动作映射

	//添加、绑定ActionKeyMapping轴映射 方法一
	FInputActionKeyMapping onFire("OnFire", EKeys::LeftMouseButton, 0, 0, 0, 0);
	UPlayerInput::AddEngineDefinedActionMapping(onFire);
	PlayerInputComponent->BindAction("OnFire", IE_Pressed, this, &AMyCharacter::OnFire);

	//添加、绑定ActionKeyMapping轴映射 方法二
	UPlayerInput::AddEngineDefinedActionMapping(FInputActionKeyMapping("Sprint",EKeys::LeftShift));
	PlayerInputComponent->BindAction("Sprint", IE_Pressed,this,&AMyCharacter::StartSprint);
	PlayerInputComponent->BindAction("Sprint", IE_Released,this,&AMyCharacter::StopSprint);

	//添加、绑定AxisMapping轴映射
	UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("Turn", EKeys::MouseX, 1.0f));
	PlayerInputComponent->BindAxis("Turn", this, &AMyCharacter::OnTurn);

碰撞检测事件绑定

碰撞对象通道与预设

  • 默认提供碰撞对象类型,如WorldStatic、WorldDynamic等,允许用户自定义
  • 默认提供碰撞预设,如NoCollision、BlockAll、OverlapAll。允许用户自定义

碰撞响应设置:是否模拟物理碰撞以及触发Overlap事件

碰撞响应类型:Blokc、Overlap、Ignore

C++实现

  • 注意Overlap Begin/End 的函数参数
  • 注意OnHit的函数参数
  • 注意Generated Hit Event的函数名
  • 绑定函数可以用AddDynamic,也可以用FScriptDelegate委托
  • 部分设置可不写,蓝图使用时再手动设置
  • 写法支持UShapeComponent及其派生类,如USphereComponent、UBoxComponent等
    UPROPERTY(EditAnywhere)
		USceneComponent* Root;

	UPROPERTY(EditAnywhere)
		UStaticMeshComponent* Cube;

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

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

	UFUNCTION()
		virtual void OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit);
ACollisionActor::ACollisionActor()
{
 	// 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;

	Root = CreateDefaultSubobject<USceneComponent>(TEXT("RootScene"));
	SetRootComponent(Root);

	Cube = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("Cube"));
	Cube->SetupAttachment(Root);
	static ConstructorHelpers::FObjectFinder<UStaticMesh> mesh(TEXT("StaticMesh'/Engine/BasicShapes/Cube.Cube'"));
	if (mesh.Succeeded())
	{
		Cube->SetStaticMesh(mesh.Object);
	}

	// 设置是否开启物理模拟
	Cube->SetSimulatePhysics(false);

	// 开启 Generated Hit Event
	Cube->SetNotifyRigidBodyCollision(true);
	
	// 开启CCD Continuous collision detection (CCD) 连续式碰撞检测
	Cube->BodyInstance.SetUseCCD(true);
	
	// 开启Generate Overlap Events
	Cube->SetGenerateOverlapEvents(true);

	// 设置碰撞预设
	Cube->SetCollisionProfileName(TEXT("OverlapAll"));
	//Cube->SetCollisionResponseToAllChannels(ECR_Overlap);

	// 设置碰撞响应设置
	Cube->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);

	// 绑定函数
	Cube->OnComponentBeginOverlap.AddDynamic(this, &ACollisionActor::OnOverlapBegin);

	// 绑定函数 使用委托
	FScriptDelegate OverlapEndDelegate;
	OverlapEndDelegate.BindUFunction(this, TEXT("OnOverlapEnd"));
	Cube->OnComponentBeginOverlap.Add(OverlapEndDelegate);
	
	// 绑定碰撞函数
	Cube->OnComponentHit.AddDynamic(this, &ACollisionActor::OnHit);
}
void ACollisionActor::OnOverlapBegin(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	UE_LOG(LogTemp, Warning, TEXT("Overlap Begin"));
}

void ACollisionActor::OnOverlapEnd(UPrimitiveComponent* OverlappedComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
	UE_LOG(LogTemp, Warning, TEXT("Overlap End"));
}

void ACollisionActor::OnHit(UPrimitiveComponent* HitComponent, AActor* OtherActor, UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit)
{
	UE_LOG(LogTemp, Warning, TEXT("Hit"));
	Destroy();
}

定时器Timer与事件绑定

  • 定时执行操作,可执行一次,或循环执行直到手动终止
  • 定时器在全局定时管理器(FTimerManager类型)中管理。全局定时器管理器存在于游戏实例对象上以及每个场景中
  • 定时器需要绑定委托或函数、作为执行体。这些函数将填充FTimerHandle定时器句柄
  • FTimerHandle支持暂停、恢复倒计时;查询或更改剩余时间;取消定时器
  • 设置定时器的函数
    • SetTimer 定时执行
    • SetTimerForNextTick 下一帧执行
  • 案例
    • 定时SpawnActor
    • 定时销毁
    • buff持续、如霸体、持续伤害

设置定时器:SetTimer

  • 支持FTimerDelegate委托,可以扩展使用Lambda表达式,可以带参数
template<class UserClass>
void SetTimer
(
    FTimerHandle & InOutHandle,
    UserClass * InObj,
    typename FTimerDelegate::TUObjectMethodDelegate_Const< UserClass >::FMethodPtr InTimerMethod,
    float InRate,
    bool InbLoop,
    float InFirstDelay
)
FTimerHandle SpawnerHandle;

GetWorldTimerManager().SetTimer(SpawnerHandle, this, &AEnenmySpawner::SpawnEnemy, 5.0f, true);	

void AEnenmySpawner::SpawnEnemy()
{
	GEngine->AddOnScreenDebugMessage(-1, 1.0f, FColor::Red, "Spawn");
}

清空定时器:ClearTimer

  • ClearAllTimerForObject:清空与特定对象关联的所有定时器
GetWorldTimerManager().ClearTimer(SpawnerHandle);

// 参数传入一个对象,本例以 this 举例
GetWorldTimerManagerr().ClearAllTimersForObject(this);

暂停和恢复:PauseTimer和UnPauseTimer

GetWorldTimerManager().PauseTimer(SpawnerHandle);
GetWorldTimerManager().UnPauseTimer(SpawnerHandle);
GetWorldTimerManager().IsTimerPaused(SpawnerHandle);

判断是否活跃且未暂停:IsTimerActive

GetWorldTimerManager().IsTimerActive(SpawnerHandle);

获取定时器速率:GetTImerRate

句柄若无效则返回-1

GetWorldTimerManager().GetTimerRate(SpawnerHandle);

获取经过时间和剩余时间:GetTimerElapsed & GetTimerRemaining


句柄若无效,返回-1

句柄若无效,返回-1

GetWorldTimerManager().GetTimerElapsed(SpawnerHandle);
GetWorldTimerManager().GetTimerRemaining(SpawnerHandle);

猜你喜欢

转载自blog.csdn.net/Jason6620/article/details/126528304