SetTimer() and general delegate question

I’ve got a couple of questions from this tutorial, the first is about the SetTimer() function. I tried to look this up in the documentation under FTimerManager and I think we’re using the following (please see comments):

//From the PawnTurret class. I think this version is: https://docs.unrealengine.com/4.26/en-US/API/Runtime/Engine/FTimerManager/SetTimer/5/
GetWorld()->GetTimerManager().SetTimer(FireRateTimerHandle, this, &APawnTurret::CheckFireCondition, FireRate, true);

//From the TankGameMode class. I think this version is: https://docs.unrealengine.com/4.26/en-US/API/Runtime/Engine/FTimerManager/SetTimer/2/
GetWorld()->GetTimerManager().SetTimer(PlayerEnableHandle, PlayerEnableDelegate, (float)StartDelay, false);    

The second one makes sense to me, but in the first one, I can’t draw the connection between what we’ve written for the 3rd parameter and what the documentation says is needed there. I can sort of see the part that says “< UserClass >::FMethodPtr” in what we’ve used, but I don’t understand the syntax in the first part of the parameter (as it’s given in the documentation).

The second question is about the following line in TankGameMode:

 FTimerDelegate PlayerEnableDelegate = 
            FTimerDelegate::CreateUObject(PlayerControllerRef,
            &APlayerControllerBase::SetPlayerEnabledState, true);

If I hover over “CreateUObject”, part of the pop-up says “Creates a UObject based member function delegate”. If I hover over “FTimerDelegate”, the pop-up says “Declares a delegate that can only bind to one native function at a time”. Is the function it binds to “SetPlayerEnabledState”, which “delegates” its functionality to the PlayerEnableDelegate (which we then call in the SetTimer() function below when the timer pings)?

Also, the documentation for FTimerDelegate doesn’t show any member functions, but the syntax seems to indicate that CreateUObject is a member function of FTimerDelegate. Is that correct, and where can I find the documentation that would tell me that?

  1. It’s for a pointer to member function. Pointer to member functions are… weird.
    See this FAQ

  2. Basically, yes. It is actually used in the other function. It just does it internally with 0 arguments. i.e.

    .SetTimer(FireRateTimerHandle, FTimerDelegate::CreateUObject(this, &APawnTurret::CheckFireCondition), FireRate, true);
    

    Should be the same thing as the first use.

  3. That would be because it’s a type alias for TDelegate<void()>
    TDelegate< InRetValType(ParamTypes...), UserPolicy > | Unreal Engine Documentation

Thinking about this practically for now,

The documentation for the .SetTimer() version we used in PawnTurret says “Sets a timer to call the given native function at a set interval.”

The documentation for the version we use in TankGameMode says “Version that takes any generic delegate”

So I’m wondering whether the reason we use the TankGameMode version where we do is because the function we’re calling is in a different class, i.e. it isn’t a member function. Whereas in PawnTurret, we’re calling a function on the same class. Is that the reason? Presumably the PawnTurret version has other benefits.

That aside, it feels that there’s a lot I’d have to read up on there before getting to the bottom of what’s going on, why things are done this way, and how much is Unreal vs C++.

That’s still a member function. If SetPlayerEnabledState had 0 parameters you can use the first overload for PlayerEnableHandle.

GetWorld()->GetTimerManager().SetTimer(PlayerEnableHandle, PlayerControllerRef, &APlayerControllerBase::SetPlayerEnabledState, (float)StartDelay, false);    

Like I said, it’s the same thing as the code internally uses the same thing. It just doesn’t provide a means to give any arguments if it’s needed for the member function.


It’s a mix really. Using standard C++

#include <chrono>
#include <iostream>
#include <thread>

using namespace std::chrono_literals;

struct Bob
{
    int value = 0;
    void print_value()
    {
        std::cout << value << '\n';
    }
    void print_squared_value()
    {
        std::cout << value * value << '\n';
    }
};

void timer(Bob Instance, void (Bob::* Func)())
{
    for (int i = 0; i < 10; ++i)
    {
        (Instance.*Func)(); // call pointer to member function on Instance
        std::this_thread::sleep_for(500ms);
    }
}

int main()
{
    Bob b{ 10 };

    timer(b, &Bob::print_value); 
    timer(b, &Bob::print_squared_value); 

    // Or see via separate thread for timers.
    //std::thread t1(timer, b, &Bob::print_value); 
    //std::thread t2(timer, b, &Bob::print_squared_value); 
    //t1.join();
    //t2.join();
}

I say “mix” because Unreal doesn’t actually use the pointer to member function you pass into it. They use their reflection system and use the name of the function. The code is just used for a compile time check that the function is valid.

This topic was automatically closed 20 days after the last reply. New replies are no longer allowed.

Privacy & Terms