【UE4

您所在的位置:网站首页 ue4自定义事件 【UE4

【UE4

2023-12-03 04:19| 来源: 网络整理| 查看: 265

七、创建自定义事件

自定义代理非常有用,但是它们的一个局限性是可以由其他第三方类在外部广播; 也就是说,它们的 execute / broadcast 方法是可公开访问的。

有时,我们可能需要一个代理,该代理可由其他类在外部分配,但只能由包含它们的类广播。 这是事件的主要目的。

这一小节,还是基于前面的GameMode和MyTriggerVolume来进行。

创建新类:

添加代码:

 MyTriggerVolume.h

// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"#include "GameFramework/Actor.h"#include "Components/BoxComponent.h"#include "MyTriggerVolume.generated.h"DECLARE_EVENT(AMyTriggerVolume, FPlayerEntered)UCLASS()class NEWTUTORIALPROJECT_API AMyTriggerVolume : public AActor{    GENERATED_BODY()    public:     // Sets default values for this actor's properties    AMyTriggerVolume();    UPROPERTY()        UBoxComponent* TriggerZone;    UFUNCTION()        virtual void NotifyActorBeginOverlap(AActor* OtherActor) override;    UFUNCTION()        virtual void NotifyActorEndOverlap(AActor* OtherActor) override;    FPlayerEntered OnPlayerEntered;protected:    // Called when the game starts or when spawned    virtual void BeginPlay() override;public:     // Called every frame    virtual void Tick(float DeltaTime) override;        };MyTriggerVolume.cpp// Fill out your copyright notice in the Description page of Project Settings.#include "MyTriggerVolume.h"#include "Engine/Engine.h"#include "Kismet/GameplayStatics.h"#include "GameFramework/GameModeBase.h"#include "RPG/InventoryGameMode.h"#include "Engine/World.h"// Sets default valuesAMyTriggerVolume::AMyTriggerVolume(){    // 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;    // Create a new component for the instance and initializeit    TriggerZone = CreateDefaultSubobject("TriggerZone");    TriggerZone->SetBoxExtent(FVector(200, 200, 100));}void AMyTriggerVolume::NotifyActorBeginOverlap(AActor* OtherActor){    auto Message = FString::Printf(TEXT("%s entered me"), *(OtherActor->GetName()));    GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Red, Message);    // Call our delegate     UWorld* TheWorld = GetWorld();    if (TheWorld != nullptr)    {        AGameModeBase* GameMode = UGameplayStatics::GetGameMode(TheWorld);        AInventoryGameMode * MyGameMode = Cast(GameMode);        if (MyGameMode != nullptr)        {            MyGameMode->MyStandardDelegate.ExecuteIfBound();            // Call the function using a parameter             auto Color = FLinearColor(1, 0, 0, 1);            MyGameMode->MyParameterDelegate.ExecuteIfBound(Color);            MyGameMode->MyMulticastDelegate.Broadcast();            OnPlayerEntered.Broadcast();        }    }}void AMyTriggerVolume::NotifyActorEndOverlap(AActor* OtherActor){    auto Message = FString::Printf(TEXT("%s left me"), *(OtherActor->GetName()));    GEngine->AddOnScreenDebugMessage(-1, 1, FColor::Red, Message);}// Called when the game starts or when spawnedvoid AMyTriggerVolume::BeginPlay(){    Super::BeginPlay();}// Called every framevoid AMyTriggerVolume::Tick(float DeltaTime){    Super::Tick(DeltaTime);}TriggerVolEventListener.h// Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreMinimal.h"#include "GameFramework/Actor.h"#include "MyTriggerVolume.h"#include "Components/PointLightComponent.h"#include "TriggerVolEventListener.generated.h"UCLASS()class NEWTUTORIALPROJECT_API ATriggerVolEventListener : public AActor{    GENERATED_BODY()    public:     // Sets default values for this actor's properties    ATriggerVolEventListener();    UPROPERTY()         UPointLightComponent* PointLight;    UPROPERTY(EditAnywhere)        AMyTriggerVolume* TriggerEventSource;    UFUNCTION()         void OnTriggerEvent();protected:    // Called when the game starts or when spawned    virtual void BeginPlay() override;public:     // Called every frame    virtual void Tick(float DeltaTime) override;        };TriggerVolEventListener.cpp// Fill out your copyright notice in the Description page of Project Settings.#include "TriggerVolEventListener.h"// Sets default valuesATriggerVolEventListener::ATriggerVolEventListener(){    // 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;    PointLight = CreateDefaultSubobject("PointLight");     RootComponent = PointLight;}void ATriggerVolEventListener::OnTriggerEvent(){    PointLight->SetLightColor(FLinearColor(0, 1, 0, 1));}// Called when the game starts or when spawnedvoid ATriggerVolEventListener::BeginPlay(){    Super::BeginPlay();    if (TriggerEventSource != nullptr)     {               TriggerEventSource->OnPlayerEntered.AddUObject(this,&ATriggerVolEventListener::OnTriggerEvent);    }}// Called every framevoid ATriggerVolEventListener::Tick(float DeltaTime){    Super::Tick(DeltaTime);}

编译完成后。在编辑器中我们拖拽一个TriggerVolEventListener到场景中,并且使用滴管选取MyTriggerVolume:

运行程序后,角色进去触发体后TriggerVolEventListener中的灯就亮起来了。

总结:

与所有其他类型的代理一样,事件需要它们自己的特殊宏函数。 第一个参数是要将事件实现到的类。 这将是唯一能够调用 Broadcast ()的类,因此要确保它是正确的类。 第二个参数是新事件函数签名的类型名称。 我们将这种类型的实例添加到类中。 虚幻的文档建议把 On 作为一个变数命名原则。

当某些内容与我们的 TriggerVolume 重叠时,我们在自己的事件实例上调用 Broadcast ()。 在新类中,我们创建一个点光源作为被触发事件的视觉表示。

我们还创建了一个指向 TriggerVolume 的指针来监听事件。 我们将 UPROPERTY 标记为 EditAnywhere,因为这允许我们在编辑器中设置它,而不必使用 GetAllActorsOfClass 或其他方法通过编程获取引用。

最后一个是我们的事件处理程序,用于当有东西进入 TriggerVolume 时进行处理。 我们像往常一样在构造函数中创建和初始化点光源。 当游戏启动时,监听器检查 TriggerVolume 引用是否有效,然后将 OnTriggerEvent 函数绑定到 TriggerVolume 事件。 在 OnTriggerEvent 中,我们将灯的颜色更改为绿色。 当某个东西进入 TriggerVolume 时,它会导致 TriggerVolume 在其自己的事件上调用广播。 然后调用我们的 TriggerVolEventListener 的绑定方法,改变灯的颜色。



【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3