简体   繁体   English

"UE4 使用具有自己参数的函数作为参数,C++"

[英]UE4 using a Function as parameter with it's own parameters, C++

I am trying to set a timer, and use a function with in. I read the timer documentation and figured out how it works.我正在尝试设置一个计时器,并在 in 中使用一个函数。我阅读了计时器文档并弄清楚了它是如何工作的。 You setting a timer with a timer_handler and a function to execute.您使用 timer_handler 和要执行的函数设置计时器。 Here's the problem.这就是问题所在。 I can only give function without parameters.我只能给出没有参数的函数。

GetWorldTimerManager().SetTimer(timer_handle1, this, &actor_class:Foo, 2.f, false, 1.f);

Use the overload of SetTimer<\/code> that takes in a lambda<\/a> .使用接收 lambda<\/a>的SetTimer<\/code>的重载。 Then call your function with parameters inside the lambda.然后使用 lambda 中的参数调用您的函数。

GetWorld()->GetTimerManager().SetTimer(
                timer_handle1,
                [&]() { this->Foo(123); },
                2.f,
                false,
                1.f);

You can also do this, Check this out:你也可以这样做,看看这个:

Unreal Engine Lambdas for Timers 用于计时器的虚幻引擎 Lambda

If you want an action performed just for the duration of a timer or any number of timers, and you don't need to keep that function around, you can also use Unreal Engine's CreateLambda .如果您希望某个操作仅在一个计时器或任意数量的计时器期间执行,并且您不需要保留该函数,您还可以使用 Unreal Engine 的CreateLambda That way you don't necessarily have to create any extra member methods in your class for a timer specifically.这样您就不必在您的类中专门为计时器创建任何额外的成员方法。

You can try something like this:你可以尝试这样的事情:

void ADynamicCamera::BlendCameraInAndOut(ACharacter* InCharacter, UCharacterMovementComponent* InCharacterMovement)
{
    if (InCharacterMovement->IsWalking())
    {
        InCharacterMovement->DisableMovement();
        APlayerController* PlayerController = UGameplayStatics::GetPlayerController(this, 0);
        check(PlayerController);
        PlayerController->SetIgnoreLookInput(true);
        PlayerController->SetViewTargetWithBlend(this, BlendTime);
        FTimerHandle TimerHandle;
        /** The first lambda (which happens when the player steps on the TriggerBox) 
         *  can capture the Timerhandle by reference to pass it to the second lambda delegate.
         *  All other values have to be captured by value otherwise you will get a nullptr crash.
         */
        GetWorldTimerManager().SetTimer(TimerHandle, FTimerDelegate::CreateLambda([=, &TimerHandle]
        {
            check(InCharacter);
            PlayerController->SetViewTargetWithBlend(InCharacter, CameraBlendTimer);
            GetWorldTimerManager().SetTimer(TimerHandle, FTimerDelegate::CreateLambda([=]
            {
                check(InCharacterMovement && PlayerController);
                InCharacterMovement->SetMovementMode(MOVE_Walking);
                PlayerController->SetIgnoreLookInput(false);
            }), CameraBlendTimer, false);
        }), CameraBlendTimer, false);
    }
}

Checkout the DelegateSignatureImpl.inl file in the following engine folder, starting from line 139 (UE5) for more information about different function delegates that are available:查看以下引擎文件夹中的DelegateSignatureImpl.inl文件,从第 139 行 (UE5) 开始,了解有关可用的不同函数委托的更多信息:

"Engine\\Source\\Runtime\\Core\\Public\\Delegates\\DelegateSignatureImpl.inl" “引擎\\源\\运行时\\核心\\公共\\委托\\委托签名Impl.inl”

You can also use a custom TFUNCTION wrapper to call on other kinds of delegates, like DYNAMIC_MULTICAST_DELEGATES.您还可以使用自定义 TFUNCTION 包装器来调用其他类型的委托,例如 DYNAMIC_MULTICAST_DELEGATES。 That way you can have even more flexibility and additional functionality.这样您就可以拥有更大的灵活性和更多的功能。 You can create your custom wrapper like this:您可以像这样创建自定义包装器:

UCLASS()
class SOME_API ULambdaWrapper final : public UObject
{
    GENERATED_BODY()
public:
    TFunction<void()> CallFunction;

    UFUNCTION()
    void DelegateDispatch() { CallFunctor(); }
};

And call them on your delegates like this:并像这样称呼他们为您的代表:

void AInGameHUD::LoadALevel(const FName& InLevelName)
{
    if (InLevelName != "")
    {
        if (LoadingScreenWidget != nullptr)
        {
            LoadingScreenWidget->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
            LoadingScreenWidget->SetFade(1.0f);
            ULambdaWrapper* LoadingScreenIsDoneFadingWrapper = NewObject<ULambdaWrapper>();
            LoadingScreenIsDoneFadingWrapper->CallFunctor = [this, InLevelName]
            {
                UGameplayStatics::OpenLevel(this, InLevelName);
            };
            LoadingScreenWidget->OnDoneFadingEvent().AddDynamic(LoadingScreenIsDoneFadingWrapper, &ULambdaWrapper::DelegateDispatch);
        }
    }
    else
    {
        UE_LOG(LogUObjectGlobals, Fatal, TEXT("Empty level name. Please add the correct level name and try again."));
    }
}

Objects created from TFUNCTIONs are intended to be used like standard C++ std::function.从 TFUNCTION 创建的对象旨在像标准 C++ std::function 一样使用。 That is:那是:

  • They take a copy of whatever is bound to them, meaning you can return them from functions and store them in objects without caring about the lifetime of the original object being bound.它们获取绑定到它们的任何内容的副本,这意味着您可以从函数中返回它们并将它们存储在对象中,而无需关心被绑定的原始对象的生命周期。 They can also have any number of parameters and have a return type.它们还可以具有任意数量的参数并具有返回类型。

TFUNCTION is explained more with an example in Function.h in the following engine folder starting from line 878 (UE5):从第 878 行(UE5)开始,以下引擎文件夹中的Function.h中的示例对 TFUNCTION 进行了更多说明:

"\\Engine\\Source\\Runtime\\Core\\Public\\Templates\\Function.h" "\\Engine\\Source\\Runtime\\Core\\Public\\Templates\\Function.h"

Hope this helps a little.希望这有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM