x

Search in
Sort by:

Question Status:

Search help

  • Simple searches use one or more words. Separate the words with spaces (cat dog) to search cat,dog or both. Separate the words with plus signs (cat +dog) to search for items that may contain cat but must contain dog.
  • You can further refine your search on the search results page, where you can search by keywords, author, topic. These can be combined with each other. Examples
    • cat dog --matches anything with cat,dog or both
    • cat +dog --searches for cat +dog where dog is a mandatory term
    • cat -dog -- searches for cat excluding any result containing dog
    • [cats] —will restrict your search to results with topic named "cats"
    • [cats] [dogs] —will restrict your search to results with both topics, "cats", and "dogs"

Can I call timer handler before delay passed?

I set timer with FTimerManager like this.

 FTimerManager& TimerManager = GetTimerManager();
 TimerManager.SetTimer(Handler, Callback, 1.0f, false);

I have two questions.

  1. In some cases, I want to Callback function before 1 sec passed. Can I do with Handler?

  2. I want to call this timer only once. After Callback function called, I expects Handler might be Invalidate but it's validate. Of course, FTimerManager::InternalClearTimer() can't find FTimerData* by FindTimer() so it's not big problem, but if I know it's only for once, I don't want to call FindTimer() in ClearTimer(). Can I tell Callback function is called or not with TimerHandle?

Product Version: UE 4.18
Tags:
more ▼

asked Mar 02 '18 at 06:01 AM in C++ Programming

avatar image

rigmania
14 3 4 10

(comments are locked)
10|2000 characters needed characters left

1 answer: sort voted first

Hello.

Clean-ish solution to do that would require to modify the engine (FTimerManager class to be specific).You'd need to expose a function that either returns non-const pointer to*FTimerData (and then call Execute on inner TimerDelegate*) or does that for your without exposing such data - this would probably be safer solution.

As an ugly workaround without modifying the engine you'd have to duplicate some data from FTimerManager. You'd have to have storage that would hold map timer handle -> delegate, and custom functions for setting up/clearing/firing timers.

Storage would be something like this:

     struct FStorageEntry 
     {
         FStorageEntry(const FTimerHandle& InHandle, const FTimerDelegate& InDelegate)
             : Handle(InHandle)
             , Delegate(InDelegate)
         {}
 
         FTimerHandle Handle;
         FTimerDelegate Delegate;
     };
 
     // TMap<FTimerHandle, FTimerDelegate> in most cases would be more efficient here
     // but FTimerHandle cannot be used as key unfortunately.
     TArray<FStorageEntry> Storage;

And setting up/execution functions:

 void UCustomTimerManager::SetupTimer(FTimerHandle& OutTimwer)
 {
     if( GEngine )
     {
         GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Yellow, TEXT("Setting up timer"));
     }
 
     UWorld* World = GetWorld();
     if( !World ) return;
 
     FTimerDelegate Delegate;
     Delegate.BindUObject(this, &UCustomTimerManager::TimerFunction);
 
     World->GetTimerManager().SetTimer(OutTimwer, Delegate, 10.f, false);
 
     Storage.Add(FStorageEntry(OutTimwer, Delegate));
 }
 
 void UCustomTimerManager::ExecuteTimer(FTimerHandle& InOutTimerHandle)
 {
     if( GEngine )
     {
         GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Yellow, TEXT("Executing timer"));
     }
 
     if( !InOutTimerHandle.IsValid() ) return;
 
     UWorld* World = GetWorld(); // you should make sure this manager can actually reference to world
     if( !World ) return;
 
     for( int32 It = 0; It < Storage.Num(); ++It )
     {
         if( Storage[It].Handle == InOutTimerHandle )
         {
             Storage[It].Delegate.Execute();
 
             Storage.RemoveAt(It);
             World->GetTimerManager().ClearTimer(InOutTimerHandle);
 
             break;
         }
     }
 }
 
 // Just for testing purposes
 void UCustomTimerManager::TimerFunction()
 {
     if( GEngine )
     {
         GEngine->AddOnScreenDebugMessage(-1, 2.f, FColor::Yellow, TEXT("Timer function executed"));
     }
 }

This is not a complete solution ofc, but you should get the idea from that. Tested and works.

Personally, I'd prefer to modify the engine as 2nd solution is kind of ugly imo.

Cheers.

more ▼

answered Mar 02 '18 at 11:43 PM

avatar image

Atheist91
1.1k 18 23 38

avatar image rigmania Mar 06 '18 at 07:43 AM

Thanks for your idea. :)

avatar image Atheist91 Mar 06 '18 at 08:26 AM

You're welcome. :]

(comments are locked)
10|2000 characters needed characters left
Your answer
toggle preview:

Up to 5 attachments (including images) can be used with a maximum of 5.2 MB each and 5.2 MB total.

Follow this question

Once you sign in you will be able to subscribe for any updates here

Answers to this question