Download

Multiple pointers for a single character (and Timelines) in c++

Hi guys. I’m currently developing an FPS game. So i’m using the character.h as a base for my controller. Yesterday i found a strange thing that i can’t explain. I created a timeline for my camera effects (like head bobing). So this timeline is binded to a function that storage my vector to use it after in a camera offset position. The thing is that the pointer for “this” (my character) in the binded function is different from the others, so the changes are not applied to my current character.

So my timeline actually works and when i debug my vector in LocationCameraEffect (timeline binded function), it returns ths right values but cameraEffectOffsetLocation(vector to stock my value) is a null vector when it is called in my tick function.

Here is my code and more details :

Only usefull lines are linked
**
Player.h :**

This a struct to create a camera effect with a timeline for the location and another for the rotation. And some bools as settings.


USTRUCT(BlueprintType, Category = "Beast | Camera Effect")
struct FCameraEffect
{
	GENERATED_USTRUCT_BODY()

	FTimeline locationTimeline;

	FTimeline rotationTimeline;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Beast |Camera Effect")
	bool usePlaybackPosition;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Beast |Camera Effect")
	bool bIsLooping;
	
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Beast |Camera Effect")
	float animationSpeed;

	FCameraEffect(){
		usePlaybackPosition = false;
		bIsLooping = false;
		animationSpeed = 1;
	}
};

How i create a timeline (example : idle):



UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Beast | Camera Effect")
UCurveVector* idleLocationCameraEffectCurve;

UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Beast | Camera Effect")
UCurveVector* idleRotationCameraEffectCurve;

FTimeline idleLocationCameraEffectTimeline;

FTimeline idleRotationCameraEffectTimeline;

CameraEffect idleCameraEffect;

Player.cpp

Constructor :



const ConstructorHelpers::FObjectFinder<UCurveVector> CurveIdleL(TEXT("CurveVector'/Game/Blueprints/PlayerBeast/Player_Curves/idleLocationCameraEffectCurve.idleLocationCameraEffectCurve'"));
idleLocationCameraEffectTimeline = FTimeline{};
FOnTimelineVector vectorLerpIdleLocation{};
vectorLerpIdleLocation.BindUFunction(this, "LocationCameraEffect");
idleLocationCameraEffectTimeline.AddInterpVector(CurveIdleL.Object, vectorLerpIdleLocation);

const ConstructorHelpers::FObjectFinder<UCurveVector> CurveIdleR(TEXT("CurveVector'/Game/Blueprints/PlayerBeast/Player_Curves/idleRotationCameraEffectCurve.idleRotationCameraEffectCurve'"));
idleRotationCameraEffectTimeline = FTimeline{};
FOnTimelineVector vectorLerpIdleRotation{};
vectorLerpIdleRotation.BindUFunction(this, "RotationCameraEffect");
idleRotationCameraEffectTimeline.AddInterpVector(CurveIdleR.Object, vectorLerpIdleRotation);

Then i bind my stuct to the existing timeline to use it later :



idleCameraEffect.locationTimeline = idleLocationCameraEffectTimeline;
idleCameraEffect.rotationTimeline = idleRotationCameraEffectTimeline;

How I start a Camera effect (some lines are commented for debugging):


void APlayerBeast::StartCameraEffect(FCameraEffect& _CameraEffect){

	if (_CameraEffect.bIsLooping && _CameraEffect.locationTimeline.IsPlaying()) return;

	// if camera effect is playing, then stop it
	if (bIsCameraEffectPlaying){
		startPlaybackPosition = currentCameraEffect.locationTimeline.GetPlaybackPosition();
		currentCameraEffect.locationTimeline.Stop();
		currentCameraEffect.rotationTimeline.Stop();
		bIsCameraEffectPlaying = false;
	}

	

	if (_CameraEffect.usePlaybackPosition) {
		_CameraEffect.locationTimeline.SetPlaybackPosition(startPlaybackPosition, true);
		_CameraEffect.rotationTimeline.SetPlaybackPosition(startPlaybackPosition, true);
	}
	else{
		//_CameraEffect.locationTimeline.SetPlaybackPosition(0, true);
		//_CameraEffect.rotationTimeline.SetPlaybackPosition(0, true);
	}

	//_CameraEffect.locationTimeline.SetPlayRate(_CameraEffect.animationSpeed);
	//_CameraEffect.rotationTimeline.SetPlayRate(_CameraEffect.animationSpeed);

	_CameraEffect.locationTimeline.Play();
	_CameraEffect.rotationTimeline.Play();
	
	currentCameraEffect = _CameraEffect;

	if (!bIsCameraEffectPlaying) bIsCameraEffectPlaying = true;
}


And the binded function to my timelines


void APlayerBeast::LocationCameraEffect(FVector _vector){
	cameraEffectOffsetLocation = _vector;
}

void APlayerBeast::RotationCameraEffect(FVector _vector){
	cameraEffectOffsetRotation = FRotator(_vector.X, _vector.Y, _vector.Z);
}

And here is the part in my tick function :


if (bIsCameraEffectPlaying){
		currentCameraEffect.locationTimeline.TickTimeline(_deltaTime);
		currentCameraEffect.rotationTimeline.TickTimeline(_deltaTime);
}

// Set Camera Position
GetBeastCamera()->SetRelativeLocation(cameraDefaultLocation + cameraEffectOffsetLocation);
GetBeastCamera()->SetRelativeRotation(cameraDefaultRotation + cameraEffectOffsetRotation);

So i found out that all this thing works correctly if i start manually each timeline :

If i dont use my StartCameraEffect() function and i directly write idleLocationCameraEffectTimeline.Play(); and make this timeine tick it works and the camera offset is correctly returned. But if i use my struct and stock my currentCameraEffect and make this one tick, the LocationCameraEffect(FVector _vector) in debug mode return another pointer for “this” when i do a quick watch in visual studio. And so my values are not applied to my cameraOffsetVector because i think this is not the same instance. Why? How? I’m lost.

I hope you understood my problem with my poor english. Do not hesitate to ask me details, i really need to understand this problem to learn how UE4 works.

up ! I really need an answer for this please :frowning:

I don’t really understand the question, but are you aware there’s a CameraShake class that does these things for you? You can also inherit a blueprint from that class and then easily set the properties for oscillation etc. in it. You can then use a node called “Client Play Camera Shake” to play this shake wherever you like.

Thanks for your answer. I already tried the CameraShake but it doesn’t provide the control i need on my camera. I just solved my problem. I had to move some part of code in the begin play when my player blueprint is already instantiated.