FTicker FTicker运行于GameThread,提供了一个静态方法CORE_API static FTicker& GetCoreTicker(),在FEngineLoop::Tick时会调用CORE_API void Tick(float DeltaTime)来对注册的FTickerDelegate进行Tick。 FTicker可以设定tick的delay time。 // Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "UObject/NoExportTypes.h" #include "Ticker.h" #include "MyTickerObject.generated.h" /** * */ UCLASS(BlueprintType) class MYPROJECT_API UMyTickerObject : public UObject { GENERATED_BODY() public: FDelegateHandle MyTickerHandle; UFUNCTION(BlueprintCallable) void Start() { MyTickerHandle = FTicker::GetCoreTicker().AddTicker(FTickerDelegate::CreateUObject(this, &UMyTickerObject::Tick));; } UFUNCTION(BlueprintCallable) void End() { FTicker::GetCoreTicker().RemoveTicker(MyTickerHandle); } bool Tick(float DeltaTime) { UE_LOG(LogTemp, Display, TEXT("UMyTickerObject Tick, %f."), DeltaTime); return true; } };
FTickableGameObject
FTickableGameObject在GEngine::Tick中被调用,FTickableGameObject::TickObjects(nullptr, LEVELTICK_All, false, DeltaSeconds)。
FTickableGameObject在构造函数中会把自身加到NewTickableObjects列表中,因此一创建就有可能tick。如果子类继承自UObject,那么CDO也会tick,但是可以通过virtual bool IsTickable() const来控制tick的时机。
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "UObject/NoExportTypes.h" #include "Tickable.h" #include "MyTickableGameObject.generated.h" /** * */ UCLASS(BlueprintType) class MYPROJECT_API UMyTickableGameObject : public UObject, public FTickableGameObject { GENERATED_BODY() public: virtual UWorld* GetTickableGameObjectWorld() const { return GetOuter()->GetWorld(); } /** * Used to determine if an object should be ticked when the game is paused. * Defaults to false, as that mimics old behavior. * * @return true if it should be ticked when paused, false otherwise */ virtual bool IsTickableWhenPaused() const { return false; } /** * Used to determine whether the object should be ticked in the editor. Defaults to false since * that is the previous behavior. * * @return true if this tickable object can be ticked in the editor */ virtual bool IsTickableInEditor() const { return false; } /** * Pure virtual that must be overloaded by the inheriting class. It will * be called from within LevelTick.cpp after ticking all actors or from * the rendering thread (depending on bIsRenderingThreadObject) * * @param DeltaTime Game time passed since the last call. */ virtual void Tick(float DeltaTime) { UE_LOG(LogTemp, Display, TEXT("UMyTickableGameObject Tick, %f."), DeltaTime); TArray<UObject*> ReferredToObjects; //req outer, ignore archetype, recursive, ignore transient FReferenceFinder ObjectReferenceCollector(ReferredToObjects, this, false, true, true, false); ObjectReferenceCollector.FindReferences(this); for (auto* object: ReferredToObjects) { UE_LOG(LogTemp, Display, TEXT("%s"), *object->GetName()); } } /** * Virtual that can be overloaded by the inheriting class. It is * used to determine whether an object will ever be able to tick, and if not, * it will not get added to the tickable objects array. If the tickable tick type * is Conditional then the virtual IsTickable will be called to determine whether * to tick the object on each given frame * * @return true if object will ever want to be ticked, false otherwise. */ virtual ETickableTickType GetTickableTickType() const { return ETickableTickType::Conditional; } /** * Virtual that can be overloaded by the inheriting class. It is * used to determine whether an object is ready to be ticked. This is * required for example for all UObject derived classes as they might be * loaded async and therefore won't be ready immediately. * * @return true if object is ready to be ticked, false otherwise. */ virtual bool IsTickable() const { return !HasAnyFlags(EObjectFlags::RF_ClassDefaultObject); } /** return the stat id to use for this tickable **/ virtual TStatId GetStatId() const { return TStatId(); } };