Skip to content

Instantly share code, notes, and snippets.

@lordliquid
Last active October 8, 2023 04:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lordliquid/b090369372fdb6912462f3292ace5f16 to your computer and use it in GitHub Desktop.
Save lordliquid/b090369372fdb6912462f3292ace5f16 to your computer and use it in GitHub Desktop.
RunOnce Delegate in Unreal Engine
#include "CoreMinimal.h"
class FRunOnce
{
public:
FORCEINLINE FRunOnce() : bHasRan(false) {}
FORCEINLINE explicit FRunOnce(const bool bStartClosed) : bHasRan(bStartClosed) {}
FORCEINLINE bool Execute() { return bHasRan ? false : bHasRan = true; }
FORCEINLINE void Reset() { bHasRan = false; }
private:
bool bHasRan;
};
template <typename... T>
class TRunOnce : TDelegate<void(T...)>
{
public:
FORCEINLINE TRunOnce() : RunOnce(MakeShared<FRunOnce>(false)) {}
FORCEINLINE explicit TRunOnce(const bool bStartClosed) : RunOnce(MakeShared<FRunOnce>(bStartClosed)) {}
FORCEINLINE bool ExecuteOnce(T... Args)
{
return RunOnce->Execute() ? TDelegate<void(T...)>::ExecuteIfBound(Args...) : false;
}
FORCEINLINE void Reset()
{
RunOnce->Reset();
}
template<typename FunctorType, typename... VarTypes>
FORCEINLINE void BindLambda(FunctorType&& Functor, VarTypes&&... Vars)
{
TDelegate<void(T...)>::BindLambda(MoveTemp(Functor), MoveTemp(Vars)...);
}
private:
TSharedPtr<FRunOnce> RunOnce;
};
class FSandboxUtilitiesModule : public IModuleInterface
{
public:
/** IModuleInterface implementation */
virtual void StartupModule() override;
virtual void ShutdownModule() override;
private:
TSharedPtr<TRunOnce<FString>> RunOnceDelegate;
};
void FSandboxUtilitiesModule::StartupModule()
{
RunOnceDelegate = MakeShared<TRunOnce<FString>>();
RunOnceDelegate->BindLambda([] (const FString& Message)
{
UE_LOG(LogTemp, Warning, TEXT("Hello from SandboxUtilitiesModule: %s"), *Message);
});
// Should only run twice total, one for each loop before and after reset.
for (int i = 0; i < 10; ++i)
{
RunOnceDelegate->ExecuteOnce(FString(TEXT("Testing RunOnceDelegate")));
}
RunOnceDelegate->Reset();
for (int i = 0; i < 10; ++i)
{
RunOnceDelegate->ExecuteOnce(FString(TEXT("Testing RunOnceDelegate")));
}
}
void FSandboxUtilitiesModule::ShutdownModule()
{
// This function may be called during shutdown to clean up your module. For modules that support dynamic reloading,
// we call this function before unloading the module.
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment