- 包括
- 默认 Tick (Actor、Component、UMG)
- TimerManager 定时器
- FTickableGameObject
- 可以写原生 Object
- 也可以继承UObject 使用
- 下面利用 AActor 直接实现三种 Tick
class FTickableObject :public FTickableGameObject
{
public:
bool bEnableTick = false;
int32 TickCounter = 0;
virtual void Tick(float DeltaTime)override {
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__"\t [TickCounter]%d"), TickCounter);
}
virtual bool IsTickable()const override { return bEnableTick; }
virtual TStatId GetStatId() const override { RETURN_QUICK_DECLARE_CYCLE_STAT(UTickableObject, STATGROUP_Tickables); }
};
UCLASS()
class DESIGNPATTERNS_API AAsyncTickActor : public AActor
{
GENERATED_BODY()
public:
// Sets default values for this actor's properties
AAsyncTickActor();
// Called every frame
virtual void Tick(float DeltaTime) override;
void TimerTick();
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
private:
int32 TickCounter = 0;
FTimerHandle TimeHandle;
TSharedPtr<FTickableObject> TickableObject;
};
AAsyncTickActor::AAsyncTickActor()
{
// 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;
}
// Called when the game starts or when spawned
void AAsyncTickActor::BeginPlay()
{
Super::BeginPlay();
TickableObject = MakeShareable(new FTickableObject());
TickableObject->bEnableTick = true;
GetWorld()->GetTimerManager().SetTimer(TimeHandle, this, &AAsyncTickActor::TimerTick, 0.1f, true);
}
// Called every frame
void AAsyncTickActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__"\t[TickCounter]%d"), TickCounter);
if (TickableObject.IsValid())
{
TickableObject->TickCounter = TickCounter;
}
}
void AAsyncTickActor::TimerTick()
{
TickCounter++;
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__"%\t [TickCounter]%d"), TickCounter);
}
异步蓝图节点
使用方法
代码实现
-
代码
UCLASS()
class DESIGNPATTERNS_API AAsyncTickActor : public AActor
{
public:
UPROPERTY(BlueprintReadWrite)
TArray<int32>CountdownNums;
};
// 定义委托类型
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FCompleteHandleDelegate, int32, Result);
UCLASS()
class DESIGNPATTERNS_API UMyBPAsyncAction : public UBlueprintAsyncActionBase
{
GENERATED_BODY()
public:
UMyBPAsyncAction() { UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__"")); }
~UMyBPAsyncAction() { UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__"")); }
// 自定义的异步蓝图节点
UFUNCTION(BlueprintCallable, meta = (WorldContext = "WorldContextObject"), Category = "MyBPAsyncAction")
static UMyBPAsyncAction* AsyncCountdown(UObject* WorldContextObject, AAsyncTickActor* AsyncTickActor, int32 StartNum);
public:
//输出节点
UPROPERTY(BlueprintAssignable)
FCompleteHandleDelegate OnSucceeded;
//输出节点
UPROPERTY(BlueprintAssignable)
FCompleteHandleDelegate OnFailed;
private:
FTimerHandle TimerHandle;
protected:
virtual void Activate() override;
};
void UMyBPAsyncAction::Activate()
{
// 开新的线程,测试 Activate 调用情况
Async(EAsyncExecution::ThreadPool, [&]()
{
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" Start Delay 1s."));
FPlatformProcess::Sleep(1.0f);
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" Delay Finished."));
});
}
UMyBPAsyncAction* UMyBPAsyncAction::AsyncCountdown(UObject* WorldContextObject, AAsyncTickActor* AsyncTickActor, int32 StartNum)
{
if (WorldContextObject == nullptr)
{
FFrame::KismetExecutionMessage(TEXT("Invalid WorldContextObject"), ELogVerbosity::Error);
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" Invalid WorldContextObject."));
return nullptr;
}
UMyBPAsyncAction* MyBPAsyncActionNode = NewObject<UMyBPAsyncAction>();
// Lambda 表达式
auto CountdownFunc = [&,MyBPAsyncActionNode, WorldContextObject, AsyncTickActor, StartNum]() {
if (IsValid(AsyncTickActor))
{
if (AsyncTickActor->CountdownNums.Num() == StartNum)
{
// OnSucceeded输出节点
MyBPAsyncActionNode->OnSucceeded.Broadcast(1);
// 清空定时器
WorldContextObject->GetWorld()->GetTimerManager().ClearTimer(MyBPAsyncActionNode->TimerHandle);
// 如果不使用,则销毁
MyBPAsyncActionNode->SetReadyToDestroy();
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" Countdown Completed."));
}
else
{
int32 length = AsyncTickActor->CountdownNums.Num();
AsyncTickActor->CountdownNums.Add(length + 1);
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" Counting down... %d"), length + 1);
}
}
else
{
// OnFailed 输出节点
MyBPAsyncActionNode->OnFailed.Broadcast(-1);
WorldContextObject->GetWorld()->GetTimerManager().ClearTimer(MyBPAsyncActionNode->TimerHandle);
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" Invalid AsyncTickActor."));
FFrame::KismetExecutionMessage(TEXT("Invalid AsyncTickActor"), ELogVerbosity::Error);
}
};
// 设置定时器并开始
WorldContextObject->GetWorld()->GetTimerManager().SetTimer(MyBPAsyncActionNode->TimerHandle, FTimerDelegate::CreateLambda(CountdownFunc), 1.0f, true);
UE_LOG(LogTemp, Warning, TEXT(__FUNCTION__" Countdown Starting."));
return MyBPAsyncActionNode;
}
Latent Action
|
请发表评论