How can I get started with FTickFunctions?

I need help with FTickFunctions.

I’m attempting to build a camera system that can be easily modified to fit my needs as my project grows. For this, Im first attempting to get the camera’s target position from the
world position of two spring arms.

The problem im running into with this is that there is a jerky motion for a frame that happens when the character changes direction. I think this is happening due to the camera grabbing its new transform position before the physics steps can complete.

If I was doing this in unity, I would add the camera transform logic into a late update function, but with unreal there isnt a late tick in the ACharacter class as far as I know. What I think I need to do is implement a FTickFunction.

The difficulty im having with that is I cant really find much information online about FTickFunctions, and im having difficulty understanding the implementation of the FTickFunction in the UCharactermovementcomponent class.

Any help would be much appreciated.

1 Like

Ive made a bit more progress with this, however im running into an issue now where I think that maybe actors cannot have more than one tick?

It seems to work fine for the UCharacterMovementComponent since it is a UComponent, but since my bow character is an ACharacter, it is not able to work.

Would it be better to instead refactor my code to have this information on a UCameraComponent instead? I dont like that the cahracter cant control the camera position with that approach, but im not too sure how else to get this camera updating to the correct position.

If you want to mess with the camera look into APlayerCameraManager and DoUpdateCamera. That’s the last step where you have pretty much the final camera transform.

If you want to still do a tick function. Do the following. Note that you need to set the proper tick group so that you get the tick order that you want.

// .h
USTRUCT()
struct FMyTickFunction : public FTickFunction
{
	GENERATED_USTRUCT_BODY()

	// Delegate allows you to bind any function to this ticker
	DECLARE_DELEGATE_OneParam(TickDelegate, float);
	TickDelegate TickFunction;

	virtual void ExecuteTick(float DeltaTime, enum ELevelTick TickType, ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent) override
	{
		TickFunction.ExecuteIfBound(DeltaTime);
	}

	virtual FString DiagnosticMessage() override { return TEXT("FMyTickFunction"); }
	virtual FName DiagnosticContext(bool bDetailed) override { return FName(TEXT("FMyTickFunction")); }
};

template<>
struct TStructOpsTypeTraits<FMyTickFunction> : public TStructOpsTypeTraitsBase2<FMyTickFunction>
{
	enum { WithCopy = false };
};

UCLASS()
class AMyActor : public AActor
{
	...

	void MyTick(float DeltaTime);

	UPROPERTY()
	FMyTickFunction MyTickFunction;
}

// .cpp
void AMyActor::MyTick(float DeltaTime)
{
	// Executed by the delegate in MyTickFunction based on TickGroup
}

void AMyActor::BeginPlay()
{
	Super::BeginPlay();

	if (!MyTickFunction.IsTickFunctionRegistered())
	{
		MyTickFunction.bRunOnAnyThread = false;
		MyTickFunction.TickGroup = ETickingGroup::TG_PostUpdateWork; // late enough for skeletal animation to be updated
		MyTickFunction.RegisterTickFunction(GetWorld()->PersistentLevel);
		MyTickFunction.TickFunction = FMyTickFunction::TickDelegate::CreateUObject(this, &AMyActor::MyTick);
	}
}

void AMyActor::EndPlay(const EEndPlayReason::Type EndPlayReason)
{
	Super::EndPlay(EndPlayReason);

	LateTickFunction.UnRegisterTickFunction();
}

1 Like

Thanks Denny!

How could I use APlayerCameraManager’s DoUpdateCamera? I haven’t used that class before.

You can either modify the camera transform directly or read its final transform before going off for rendering. You have total freedom in there with no actor or component dependencies like a camera component. I recommend looking at the base class what it is doing and learn from that as an example, FMinimalViewInfo is the struct you are interested in. This class is for example responsible for camera animations. UpdateCamera and DoUpdateCamera are the two entry points to look at.

Hi Denny, im starting to play around with the DoUpdateCamera function, though im having a bit of trouble with setting the position of the camera through FMinialViewInfo.

The problem Im having is that the camera position is not being affected by this doupdatecamera script so far.

I know there are likely a lot of set up steps I should check for this, but is this sort of how I should be doing it?

You should 99% of all times call the Super function first, otherwise that call will just overwrite what you are doing. I am also pretty sure you need to update the cached POV with SetCameraCachePOV like they do in the base class. If this class is too advanced it is probably easier to work with the tick functions.