“This is the fourth day of my participation in the First Challenge 2022. For details: First Challenge 2022”

Today, I do not know what to write, left and right, or to a UE4 source code analysis ~(gnawing Lao Ben)

This time, we’ll focus on Timeline in UE4, the C++ part of the Timeline node in the blueprint

Note: Reading this article requires UE4C++ foundation

structure

Firstly, UE4C++ uses the FTimeline structure and TimelineComponent component.

Then, TimelineCompontent is used for external control of a layer equivalent to the FTimeline encapsulation, we general project inside the actual use, should be used by TimelineComponent, should be used for FTimeline is relatively little….

Engine\Source\Runtime\Engine\Classes\Components\TimelineComponent. H Source code is too long to post.

In fact, the main structure is very simple. The outermost layer is the Timeline ontology, in which there are multiple tracks, all of which share the same Timeline configuration. Each Track corresponds to a curve, and each curve corresponds to several key frames.

It can be seen that the structure of Track is as follows:


/** Struct that contains one entry for each vector interpolation performed by the timeline */
USTRUCT(a)struct FTimelineFloatTrack
{
	GENERATED_USTRUCT_BODY(a)/** Float curve to be evaluated */
	UPROPERTY(a)class UCurveFloat* FloatCurve;

	/** Function that the output from ValueCurve will be passed to */
	UPROPERTY()
	FOnTimelineFloat InterpFunc;// Dynamic unicast delegate

	/** Name of track, usually set in Timeline Editor. Used by SetInterpFloatCurve function. */
	UPROPERTY()
	FName TrackName;

	/** The output pin name */ corresponding to the Float track reflected on the blueprint node
	UPROPERTY()
	FName FloatPropertyName;

	/** Output pin */ corresponding to the Float track on the blueprint node
	UPROPERTY(transient)
	UFloatProperty* FloatProperty;

	/** Static version of FOnTimelineFloat, for use with non-UObjects */
	FOnTimelineFloatStatic InterpFuncStatic;

	FTimelineFloatTrack()
		: FloatCurve(NULL),FloatPropertyName(NAME_None)
		, FloatProperty(NULL) {}};Copy the code

A flowchart

Call TimelineComponent: : Play, Open the Component itself Tick timer – > TimelineComponent: : TickComponent start work – > call FTimeline: : TickTimeline – > actual call FTimeline: : SetPlaybackPosit Ion to execute the events bound to the Timeline per frame.

The key function

TimelineComponent::TickComponent

void UTimelineComponent::TickComponent(float DeltaTime, enum ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	SCOPE_CYCLE_COUNTER(STAT_TimelineCompTick); 

	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	if (bIgnoreTimeDilation)
	{
		AActor* const OwnerActor = GetOwner(a);if (OwnerActor)
		{
			DeltaTime /= OwnerActor->GetActorTimeDilation(a); }else
		{
			// no Actor for some reason, use the world time dilation as fallback
			UWorld* const W = GetWorld(a);if (W)
			{
				DeltaTime /= W->GetWorldSettings() - >GetEffectiveTimeDilation(a); } } } TheTimeline.TickTimeline(DeltaTime);

	if (!IsNetSimulating())
	{
		// Do not deactivate if we are done, since bActive is a replicated property and we shouldn't have simulating
		// clients touch replicated variables.
		if(! TheTimeline.IsPlaying())
		{
			Deactivate(a); }}}Copy the code

Other code too long will not be posted, you can read.

FTimeline itself is relatively simple compared to other things in UE4, so there is not much to talk about. The main content is actually focused on the SetPlaybackPosition function, as long as you understand this function, FTimeline is not difficult to understand.

To SetPlaybackPosition has nothing to do in the part, the logical subject are VecEntry. InterpFunc. ExecuteIfBound (Vec); (This is a Vector track, and so on.) That is, the value of the current location is notified each time the location is set.

It should be noted that the structure of the Event track in FTimeline is different from other types of track. It only has the point of the key frame instead of the curve, so it is processed separately. But just because of this, it saves a lot of overhead.

Although the Timeline part of UE4 is easy to use due to its simple structure, it limits its usage scenarios. If we ignore the node UI part, it can be reconstructed to support its use anywhere. Of course, the simplicity of the UE4 Timeline structure must also be taken into account. For example, the uniqueness of the Timeline: for example, how to notify the same Timeline in all locations? It has to be multicasting, so how do you determine uniqueness in multicasting? If there are multiple timelines, how do you manage them and determine their uniqueness?

In the next series, I’ll try to make a third-party Timeline to try to solve these problems.

Reprint with indication of source.