TickTimeline() causing game to crash

Hey guys, I am currently working through my first project and have run into a problem using timelines that I cannot seem to solve. I am trying to use a timeline to animate a button being pressed. the following link shows a picture of the button http://i.imgur.com/EObTLeO.png

To implement the timeline I followed this page from the AnswerHub: https://answers.unrealengine.com/questions/115830/why-is-timeline-bindufunction-only-called-once.html

I have also made my own post on the AnswerHub about this problem here: https://answers.unrealengine.com/questions/167189/ticktimeline-access-violation.html

Below are the .h and .cpp files for my BasicButton class:

BasicButton.h


// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "GameFramework/Actor.h"
#include "BasicButton.generated.h"

/**
 * 
 */
UCLASS()
class SPACEPUZZLE_API ABasicButton : public AActor
{
	GENERATED_BODY()

	ABasicButton(const class FObjectInitializer& ObjectInitializer);	
	virtual void BeginPlay() override;		

	virtual void ReceiveHit
		(
			UPrimitiveComponent* MyComponent,
			AActor* OtherActor,
			UPrimitiveComponent* OtherComponent,
			bool bSelfMoved, FVector HitLocation,
			FVector HitNormal, FVector NormalImpulse,
			const FHitResult& Hit
		) override; //Overide the RecieveHit function from AActor to define custom behaviour

	float DELTATIME;
	UFUNCTION()
	void Anim_UpdateProgress(FVector Vec); // Function that will update the buttons position
	UFUNCTION()
	void Anim_TickTimeline();
	UFUNCTION()
	void Anim_AnimateButton();
protected:	
public:
	//PROPERTY
	UPROPERTY(BlueprintReadWrite, Category = Components)
		UPrimitiveComponent* ButtonMesh; //Pointer to the Buttons MeshComponent (To be set in Blueprints)
	UPROPERTY(BlueprintReadWrite, Category = Components)
		UCurveVector* Anim_VectorCurve;  //Pointer to the Vector Curve used in the Animation Timeline
	UPROPERTY()
		float Anim_DeltaTime; //Stepsize for the timer that will tick the timeline;
	UPROPERTY()
		FTimeline Anim_Timeline; //Timeline that will animate the button
};


BasicButton.cpp


// Fill out your copyright notice in the Description page of Project Settings.

#include "SpacePuzzle.h"
#include "BasicButton.h"

ABasicButton::ABasicButton(const class FObjectInitializer& ObjectInitializer)
:Super(ObjectInitializer)
{
	const ConstructorHelpers::FObjectFinder<UCurveVector> Curve(TEXT("CurveVector'/Game/Blueprints/Functionals/Anim_ButtonCurve.Anim_ButtonCurve'"));
	DELTATIME = 2.f;
	FOnTimelineVector ProgressDelegate{}; //Setup a Delegate to pass the Timeline. Tis will be bound to Anim_UpdateProgress()
	ProgressDelegate.BindUFunction(this, "Anim_UpdateProgress"); // Bind the delegate to our update function
	
	Anim_Timeline.AddInterpVector(Anim_VectorCurve, ProgressDelegate);
	Anim_Timeline.SetLooping(false);
	Anim_Timeline.SetPlayRate(1.f);
}

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

	if (GEngine)
	{
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("Using Basic Button"));
	}
}

void ABasicButton::ReceiveHit(UPrimitiveComponent* MyComponent, AActor* OtherActor, UPrimitiveComponent* OtherComponent, bool bSelfMoved, FVector HitLocation, FVector HitNormal, FVector NormalImpulse, const FHitResult& Hit)
{
	if (GEngine)
	{
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("HIT"));
	}

	if (Anim_Timeline.IsPlaying() == false)
	{
		Anim_AnimateButton();
	}
}



void ABasicButton::Anim_TickTimeline()
{
	if (Anim_Timeline.IsPlaying())
	{		
		Anim_Timeline.TickTimeline(DELTATIME);
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("TRYING TO Tick Timeline!"));	
	}
	else
	{
		GetWorldTimerManager().ClearTimer(this, &ABasicButton::Anim_TickTimeline);		
	}
}

void ABasicButton::Anim_UpdateProgress(FVector Vec)
{
	if (GEngine)
	{
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("TRYING TO PLAY"));
	}
	//This function is called when the timline ticks and should move the button
	if (ButtonMesh != NULL)
	{
		FVector MoveLocation = ButtonMesh->GetComponentLocation() + Vec;
		ButtonMesh->MoveComponent(Vec, ButtonMesh->GetComponentRotation(), false);
	}
}

void ABasicButton::Anim_AnimateButton()
{
	//This Function should begin playback of the animation timeline
	

		//Begin a clock that will tick with the timeline
		UWorld* World = GetWorld();
		if (World)
		{
			Anim_Timeline.PlayFromStart();
			FTimerHandle TimerHandle;
			GetWorldTimerManager().SetTimer(TimerHandle, this, &ABasicButton::Anim_TickTimeline, DELTATIME, true, 0.0f);			
		}
	
}


The Problem

Everything runs fine on start up but when the button object recieves a hit result the game crashings giving the following error message:



Access violation - code c0000005 (first/second chance not available)

UE4Editor_Engine + 2542179 bytes
UE4Editor_Engine + 8907614 bytes
UE4Editor_Engine + 8945910 bytes
UE4Editor_Engine + 9050082 bytes
UE4Editor_SpacePuzzle!ABasicButton::Anim_TickTimeline() + 61 bytes [d:\ut4project\spacepuzzle\source\spacepuzzle\basicbutton.cpp:53]
UE4Editor_Engine + 8866299 bytes
UE4Editor_Engine + 9047929 bytes
UE4Editor_Engine + 5623214 bytes
UE4Editor_UnrealEd + 1803906 bytes
UE4Editor_UnrealEd + 6686342 bytes
UE4Editor!FEngineLoop::Tick() + 3876 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.6\engine\source\runtime\launch\private\launchengineloop.cpp:2214]
UE4Editor!GuardedMain() + 479 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.6\engine\source\runtime\launch\private\launch.cpp:131]
UE4Editor!GuardedMainWrapper() + 26 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.6\engine\source\runtime\launch\private\windows\launchwindows.cpp:126]
UE4Editor!WinMain() + 249 bytes [d:\buildfarm\buildmachine_++depot+ue4-releases+4.6\engine\source\runtime\launch\private\windows\launchwindows.cpp:202]
UE4Editor!__tmainCRTStartup() + 329 bytes [f:\dd\vctools\crt\crtw32\dllstuff\crtexe.c:618]


Through a process of elimination (by commenting out lines) I have found that it is the Anim_TickTimeline() function, specifically the line:


Anim_Timeline.TickTimeline(DELTATIME);

that is causing the crash. When I comment out this line the game does not crash and after a hit event the debug message, “Trying to tick timeline” is repeatedly printed to the screen. This leads me to believe that I have not Initialized something, or the timeline is otherwise unable to tick.

Would anyone be able to help me solve this issue

I am very new to programming and UE4 so I apologize if there is something very basic that I have overlooked or otherwise don’t understand.
Thanks :slight_smile:

My quick guess is that line 53:



GetWorldTimerManager().ClearTimer(this, &ABasicButton::Anim_TickTimeline);


Is accessing a null UWorld (GetWorld() is called inside of GetWorldTimerManager()). Just a quick guess, though.

Thanks for your reply. That was my initial thought, however when I comment out the


Anim_Timeline.TickTimeline();

line the Timer begins generating the debug message “Trying to tick timeline”, which suggests that the timer is working but the timeline is crashing when it tries to tick. I have searched through the documentation to try and find out any initialization that may be required but a lot of the syntax and techniques used (delegates especially) are reaching the limits of my c++ understanding. I also considered if the problem is being caused because of poor initialization of the actor components or something, but again I am limited by my understanding of the UE4 framework.

Commenting out Anim_Timeline.TickTimeline(DELTATIME); just means that the it never advances the timeline and never reaches the end point – so it never never reaches the the ‘else’ code path. Do you see?

When I comment out that line, upon hitting the button I see a constant stream of Debug messages that say “Trying to Tick Timeline”. Since this is in the same If statement as the Anim_Timeline.TickTimeline(DELTATIME), I would think that the problem is with the TickTimeline() call and not the Timer is it not?


void ABasicButton::Anim_TickTimeline()
{
	if (Anim_Timeline.IsPlaying())
	{		
		Anim_Timeline.TickTimeline(DELTATIME);
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, TEXT("TRYING TO Tick Timeline!"));	
	}
	else
	{
		GetWorldTimerManager().ClearTimer(this, &ABasicButton::Anim_TickTimeline);		
	}
}