概述
发现了一个比较正宗的写法!!!!!!!!
https://blog.csdn.net/Bob__yuan/article/details/109689234 (3.2的那条)
通过上面的博主的方法,实现一个actor私有的timermanager,对该actor执行SetTickableWhenPaused(true)
,这就非常完美
我是真他娘的蠢驴
以下都是错误示范 不需要在意 直接看上面超链
UE4 不受游戏暂停影响的Timer /Delay C++蓝图都能用
原因
业务逻辑需要,以及因为序列帧实现的ui动图是通过tick刷的,暂停时ui tick会暂停,只能通过写一个不受暂停影响的timer去刷序列帧,为了填一个坑,而出来的另一个坑,大家都是挖坑人。
基本原理
重点就是 actor 的SetTickableWhenPaused(true)
,就是标记actor在游戏
暂停时,是否能够执行Tick(float DeltaTime)
运用了什么知识
通过FName调用蓝图方法,
C++通过委托绑定方法进行回调
蓝图异步节点(UBlueprintAsyncActionBase)
效果图
使用时必须创建一个SuperTimer对象
可以看到SetGamePause true后,我的delay没有停止,并执行了我的timer并再刷计时任务
源码 SuperTimer.h demo地址:
>下载链接: https://pan.baidu.com/s/1P4iWV87tiU94VpAlqrnm1A 提取码: j9q9
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "TimerManager.h"
#include "Kismet/BlueprintAsyncActionBase.h"
#include "GameFramework/Actor.h"
#include "SuperTimer.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FSuperDelayDelegate);
USTRUCT(BlueprintType)
struct FSuperTimerHandler
{
GENERATED_USTRUCT_BODY()
UPROPERTY(BlueprintReadWrite,EditAnywhere)
FName FunctionName;
UPROPERTY(BlueprintReadWrite, EditAnywhere)
bool Loop;
UPROPERTY(BlueprintReadWrite, EditAnywhere)
UObject* object;
UPROPERTY(BlueprintReadWrite, EditAnywhere)
float time;
bool bEnable = true;
int type = 0; //0 是蓝图 1 是c++
FTimerUnifiedDelegate* delegateFunc;
friend inline bool operator==(const FSuperTimerHandler& A, const FSuperTimerHandler& B)
{
return A.FunctionName == B.FunctionName && A.Loop == B.Loop && A.object == B.object && A.time == B.time;
}
friend inline uint32 GetTypeHash(const FSuperTimerHandler& Key)
{
uint32 Hash = 0;
Hash = HashCombine(Hash, GetTypeHash(Key.FunctionName));
Hash = HashCombine(Hash, GetTypeHash(Key.Loop));
Hash = HashCombine(Hash, GetTypeHash(Key.object));
Hash = HashCombine(Hash, GetTypeHash(Key.time));
return Hash;
}
//TODO :做一个直接通过handler对象实现清理的方法,不需要调用SuperTimer对象的方法
//就像蓝图里面的 ClearAndInvalidateTimerHandle
//
//inline void ClearThisTimer()
//{
// FSuperTimerHandler tmp = this->StaticStruct;
// ASuperTimer::GetSuperTimer()->RemoveTimer(tmp);
//}
};
UCLASS()
class MYP_API ASuperTimer : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
ASuperTimer();
UFUNCTION(BlueprintPure)
static ASuperTimer* GetSuperTimer();
UFUNCTION(BlueprintCallable,meta =(DefaultToSelf = "object"))
static FSuperTimerHandler SetSuperTimer(FName FuncName, UObject* object, bool loop, float time);
UFUNCTION(BlueprintCallable)
void ClearAllSuperTimer()
{
// TimerList.Empty();
for (auto& timer : TimerList)
{
timer.Key.bEnable = false;
}
UE_LOG(LogTemp, Warning, TEXT("Timerlist clear ,now count:%d"), TimerList.Num())
}
UFUNCTION(BlueprintCallable,meta =(DefaultToSelf = "object"))
void ClearSuperTimer(FName FuncName, UObject* object);
FSuperTimerHandler InternalSetSuperTimer(FTimerUnifiedDelegate* exefun, bool loop, float time);
//c++创建Timer,仿照ue4c++timer写的一套,直接把 ue4的 FTimerUnifiedDelegate给搬过来了
//其实虚幻源码就是通过创建delegate,时间一到直接执行delegate
template <class UserClass>
FORCEINLINE FSuperTimerHandler SetSuperTimerDelegate(UserClass* InObj,
typename FTimerDelegate::TUObjectMethodDelegate<UserClass
>::FMethodPtr InTimerMethod, bool loop, float time)
{
FTimerUnifiedDelegate* TimerDelegateFunc = new FTimerUnifiedDelegate(
FTimerDelegate::CreateUObject(InObj, InTimerMethod));
FSuperTimerHandler val = InternalSetSuperTimer(TimerDelegateFunc, loop, time);
return val;
};
//c++清理timer
void RemoveTimer(FSuperTimerHandler timer)
{
for (auto& localTimer : TimerList)
{
if (localTimer.Key == timer)
{
localTimer.Key.bEnable = false;
}
}
}
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
public:
// Called every frame
virtual void Tick(float DeltaTime) override;
protected:
TMap<FSuperTimerHandler, float> TimerList;
};
UCLASS()
class MYP_API USuperDelay : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
UPROPERTY(BlueprintAssignable)
FSuperDelayDelegate Completed;
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject", Delay =
"0.5"))
static USuperDelay* SuperDelay(UObject* WorldContextObject, float DelayTime);
protected:
void DelayCallBack()
{
if (Completed.IsBound())
{
Completed.Broadcast();
}
}
};
SuperTimer.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "SuperTimer.h"
static ASuperTimer* SuperTimerInstance = nullptr;
// Sets default values
ASuperTimer::ASuperTimer()
{
// 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;
this->SetTickableWhenPaused(true);
SuperTimerInstance = this;
}
ASuperTimer* ASuperTimer::GetSuperTimer()
{
if(!SuperTimerInstance)
{
UE_LOG(LogTemp,Warning,TEXT("Supertimer Actor not Vaild"));
}
return SuperTimerInstance;
}
FSuperTimerHandler ASuperTimer::SetSuperTimer(FName FuncName, UObject* object, bool loop, float time)
{
FSuperTimerHandler _handler;
_handler.FunctionName = FuncName;
_handler.Loop = loop;
_handler.object = object;
_handler.time = time;
_handler.bEnable = true;
_handler.type = 0;
ASuperTimer::GetSuperTimer()->TimerList.Add(_handler, time);
return _handler;
}
void ASuperTimer::ClearSuperTimer(FName FuncName, UObject* object)
{
TArray<FSuperTimerHandler> TempAllTimer;
TimerList.GetKeys(TempAllTimer);
for (auto timer : TempAllTimer)
{
if (timer.FunctionName == FuncName && timer.object == object)
{
TimerList.Remove(timer);
break;
}
}
}
FSuperTimerHandler ASuperTimer::InternalSetSuperTimer(FTimerUnifiedDelegate* exefun, bool loop, float time)
{
FSuperTimerHandler _handler;
_handler.Loop = loop;
_handler.time = time;
_handler.bEnable = true;
_handler.type = 1;
_handler.delegateFunc = exefun;
TimerList.Add(_handler, time);
return _handler;
}
// Called when the game starts or when spawned
void ASuperTimer::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void ASuperTimer::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
TArray<FSuperTimerHandler> AllTimerArray;
TimerList.GetKeys(AllTimerArray);
for (FSuperTimerHandler timer : AllTimerArray)
{
if (!timer.bEnable)
{
TimerList.Remove(timer);
continue;
}
TimerList[timer] -= DeltaTime;
if (TimerList[timer] <= 0.0f)
{
if (timer.type == 0)
{
if (!timer.object)
{
TimerList.Remove(timer);
continue;
}
UFunction* fun = timer.object->FindFunction(timer.FunctionName);
if (!fun)
{
TimerList.Remove(timer);
continue;
}
if (timer.Loop)
{
TimerList[timer] = timer.time;
}
else
{
TimerList.Remove(timer);
}
timer.object->ProcessEvent(fun, NULL);
UE_LOG(LogTemp, Warning, TEXT("Super Timer Start Calling BP %s ,Func %s"), *timer.object->GetName(),
*timer.FunctionName.ToString());
}
else
{
if (timer.Loop)
{
TimerList[timer] = timer.time;
}
else
{
TimerList.Remove(timer);
}
timer.delegateFunc->Execute();
// UE_LOG(LogTemp, Warning, TEXT("Super Timer Start Calling c++ Func "));
}
}
}
}
USuperDelay* USuperDelay::SuperDelay(UObject* WorldContextObject, float DelayTime)
{
USuperDelay* SuperDelayNode = NewObject<USuperDelay>();
ASuperTimer::GetSuperTimer()->SetSuperTimerDelegate(SuperDelayNode, &USuperDelay::DelayCallBack, false, DelayTime);
return SuperDelayNode;
}
使用时得把MYP_API 改成自己项目的 API
C++的使用下次有空在更新吧
demo奉上
下载链接: https://pan.baidu.com/s/1P4iWV87tiU94VpAlqrnm1A 提取码: j9q9
最后
以上就是难过雪碧为你收集整理的UE4 不受游戏暂停影响的Timer /Delay C++蓝图都能用发现了一个比较正宗的写法!!!!!!!!我是真他娘的蠢驴UE4 不受游戏暂停影响的Timer /Delay C++蓝图都能用的全部内容,希望文章能够帮你解决UE4 不受游戏暂停影响的Timer /Delay C++蓝图都能用发现了一个比较正宗的写法!!!!!!!!我是真他娘的蠢驴UE4 不受游戏暂停影响的Timer /Delay C++蓝图都能用所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复