First, Here’s error codes.
Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x00000000000000f0
UnrealEditor_Engine!FTimeline::AddInterpFloat() [D:\build++UE5\Sync\Engine\Source\Runtime\Engine\Private\Timeline.cpp:114]
UnrealEditor_Engine!UTimelineComponent::AddInterpFloat() [D:\build++UE5\Sync\Engine\Source\Runtime\Engine\Private\Timeline.cpp:777]
UnrealEditor_FPSurvival_5945!AFPSurvivalCharacter::BeginPlay() [C:\Users\username\Desktop\Unreal Portfolio\FPSurvival\Source\FPSurvival\FPSurvivalCharacter.cpp:82]
Every time I try to use Timeline’s member function, it shows the above error and crashes.
I connected all the delegates properly, and I don’t know why I’m doing this because I’m not going to misrepresent the parameters.
I will attach the full source code below.
// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CoreMinimal.h"
#include "Components/TimelineComponent.h"
#include "GameFramework/Character.h"
#include "FPSurvivalCharacter.generated.h"
class UInputComponent;
class USkeletalMeshComponent;
class USceneComponent;
class UCameraComponent;
class UAnimMontage;
class USoundBase;
// Declaration of the delegate that will be called when the Primary Action is triggered
// It is declared as dynamic so it can be accessed also in Blueprints
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FOnUseItem);
enum class EMovementState
{
Walking,
Sprinting,
Crouching,
Sliding
};
UCLASS(config=Game)
class AFPSurvivalCharacter : public ACharacter
{
GENERATED_BODY()
/** Pawn mesh: 1st person view (arms; seen only by self) */
UPROPERTY(VisibleDefaultsOnly, Category=Mesh)
USkeletalMeshComponent* Mesh1P;
/** First person camera */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
UCameraComponent* FirstPersonCameraComponent;
public:
AFPSurvivalCharacter();
protected:
virtual void BeginPlay() override;
virtual void Tick(float DeltaSeconds) override;
virtual void Landed(const FHitResult& Hit) override;
virtual void Jump() override;
public:
/** Base turn rate, in deg/sec. Other scaling may affect final turn rate. */
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
float TurnRateGamepad;
/** Delegate to whom anyone can subscribe to receive this event */
UPROPERTY(BlueprintAssignable, Category = "Interaction")
FOnUseItem OnUseItem;
float SprintMultiplier;
float CrouchMultiplier;
int CurrentJumpCount = 0;
int MaxJumpCount = 0;
float StandingCapsuleHalfHeight = 0;
float StandingCameraZOffset = 0;
TMap<EMovementState, float> SpeedMap;
TMap<FName, bool> ButtonPressed;
EMovementState MovementState;
EMovementState PrevMovementState;
FOnTimelineFloat SmoothCrouchInterpolateFunction;
FOnTimelineEvent SmoothCrouchTimelineFinish;
//FOnTimelineFloat SlideTimelineFunction;
UFUNCTION()
void SmoothCrouchInterpolateReturn(float Value);
UFUNCTION()
void SmoothCrouchOnFinish();
//UFUNCTION()
//void SlideTimelineReturn(float Value);
UPROPERTY()
UTimelineComponent* SmoothCrouchingCurveTimeline;
UPROPERTY(EditAnywhere, Category = "Timeline")
UCurveFloat* SmoothCrouchingCurveFloat;
//UPROPERTY(EditAnywhere, Category = "Timeline")
//UCurveFloat* SlideCurveFloat;
//UPROPERTY()
//UTimelineComponent* SlideTimeline;
protected:
/** Fires a projectile. */
void OnPrimaryAction();
bool CanStand();
bool CanSprint();
void BeginSlide();
void EndSlide();
void BeginCameraTilt();
void EndCameraTilt();
void SetMovementState(EMovementState NewMovementState);
void ResolveMovementState();
void OnMovementStateChanged();
/** Handles moving forward/backward */
void MoveForward(float Val);
/** Handles strafing movement, left and right */
void MoveRight(float Val);
/**
* Called via input to turn at a given rate.
* @param Rate This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
*/
void TurnAtRate(float Rate);
/**
* Called via input to turn look up/down at a given rate.
* @param Rate This is a normalized rate, i.e. 1.0 means 100% of desired turn rate
*/
void LookUpAtRate(float Rate);
struct TouchData
{
TouchData() { bIsPressed = false;Location=FVector::ZeroVector;}
bool bIsPressed;
ETouchIndex::Type FingerIndex;
FVector Location;
bool bMoved;
};
void BeginTouch(const ETouchIndex::Type FingerIndex, const FVector Location);
void EndTouch(const ETouchIndex::Type FingerIndex, const FVector Location);
void OnSprintAction(bool Pressed);
void OnCrouchAction(bool Pressed);
void TouchUpdate(const ETouchIndex::Type FingerIndex, const FVector Location);
TouchData TouchItem;
protected:
// APawn interface
virtual void SetupPlayerInputComponent(UInputComponent* InputComponent) override;
// End of APawn interface
/*
* Configures input for touchscreen devices if there is a valid touch interface for doing so
*
* @param InputComponent The input component pointer to bind controls to
* @returns true if touch controls were enabled.
*/
bool EnableTouchscreenMovement(UInputComponent* InputComponent);
public:
/** Returns Mesh1P subobject **/
USkeletalMeshComponent* GetMesh1P() const { return Mesh1P; }
/** Returns FirstPersonCameraComponent subobject **/
UCameraComponent* GetFirstPersonCameraComponent() const { return FirstPersonCameraComponent; }
};
// Copyright Epic Games, Inc. All Rights Reserved.
#include "FPSurvivalCharacter.h"
#include "FPSurvivalProjectile.h"
#include "Animation/AnimInstance.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/InputComponent.h"
#include "Kismet/GameplayStatics.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/InputSettings.h"
class AProjectFVSCharacter;
//////////////////////////////////////////////////////////////////////////
// AProjectFVSCharacter
AFPSurvivalCharacter::AFPSurvivalCharacter()
{
// Set size for collision capsule
GetCapsuleComponent()->InitCapsuleSize(55.f, 96.0f);
// set our turn rates for input
TurnRateGamepad = 45.f;
// Create a CameraComponent
FirstPersonCameraComponent = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
FirstPersonCameraComponent->SetupAttachment(GetCapsuleComponent());
FirstPersonCameraComponent->SetRelativeLocation(FVector(-39.56f, 1.75f, 64.f)); // Position the camera
FirstPersonCameraComponent->bUsePawnControlRotation = true;
// Create a mesh component that will be used when being viewed from a '1st person' view (when controlling this pawn)
Mesh1P = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("CharacterMesh1P"));
Mesh1P->SetOnlyOwnerSee(true);
Mesh1P->SetupAttachment(FirstPersonCameraComponent);
Mesh1P->bCastDynamicShadow = false;
Mesh1P->CastShadow = false;
Mesh1P->SetRelativeRotation(FRotator(1.9f, -19.19f, 5.2f));
Mesh1P->SetRelativeLocation(FVector(-0.5f, -4.4f, -155.7f));
SprintMultiplier = 1.7f;
CrouchMultiplier = 0.6f;
SpeedMap.Reserve(3);
SpeedMap.Add(EMovementState::Walking, GetCharacterMovement()->MaxWalkSpeed);
SpeedMap.Add(EMovementState::Sprinting, GetCharacterMovement()->MaxWalkSpeed * SprintMultiplier);
SpeedMap.Add(EMovementState::Crouching, GetCharacterMovement()->MaxWalkSpeed * CrouchMultiplier);
SpeedMap.Add(EMovementState::Sliding, NULL);
ButtonPressed.Reserve(2);
ButtonPressed.Add("Sprint", false);
ButtonPressed.Add("Crouch", false);
CurrentJumpCount = 0;
MaxJumpCount = 2;
MovementState = EMovementState::Walking;
PrevMovementState = EMovementState::Walking;
SmoothCrouchingCurveTimeline = CreateDefaultSubobject<UTimelineComponent>(TEXT("TimelineFront"));
SmoothCrouchInterpolateFunction.BindUFunction(this, FName("SmoothCrouchInterpolateReturn"));
SmoothCrouchTimelineFinish.BindUFunction(this, FName("SmoothCrouchOnFinish"));
/*SlideTimeline = CreateDefaultSubobject<UTimelineComponent>(TEXT("SlideTimeline"));
SlideTimelineFunction.BindUFunction(this, FName("SlideTimelineReturn"));*/
StandingCapsuleHalfHeight = GetCapsuleComponent()->GetScaledCapsuleHalfHeight();
StandingCameraZOffset = GetFirstPersonCameraComponent()->GetRelativeLocation().Z;
}
void AFPSurvivalCharacter::BeginPlay()
{
// Call the base class
Super::BeginPlay();
if (SmoothCrouchingCurveFloat)
{
SmoothCrouchingCurveTimeline->AddInterpFloat(SmoothCrouchingCurveFloat, SmoothCrouchInterpolateFunction);
SmoothCrouchingCurveTimeline->SetTimelineFinishedFunc(SmoothCrouchTimelineFinish);
SmoothCrouchingCurveTimeline->SetLooping(false);
//SmoothCrouchingCurveTimeline->SetTimelineLength(0.3);
}
/*if (SlideCurveFloat)
{
SlideTimeline->AddInterpFloat(SlideCurveFloat, SlideTimelineFunction);
SlideTimeline->SetTimelineLength(1.0);
SlideTimeline->SetLooping(true);
}*/
}
void AFPSurvivalCharacter::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
if(MovementState == EMovementState::Crouching && !ButtonPressed["Crouch"])
{
ResolveMovementState();
}
}
void AFPSurvivalCharacter::Landed(const FHitResult& Hit)
{
Super::Landed(Hit);
CurrentJumpCount = 0;
}
void AFPSurvivalCharacter::Jump()
{
if(CurrentJumpCount == 0)
{
Super::Jump();
CurrentJumpCount++;
}
else if (CurrentJumpCount < MaxJumpCount)
{
const FVector LaunchDir = FVector(0, 0, GetCharacterMovement()->JumpZVelocity);
LaunchCharacter(LaunchDir, false, true);
CurrentJumpCount++;
}
}
//////////////////////////////////////////////////////////////////////////// Input
void AFPSurvivalCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
// Set up gameplay key bindings
check(PlayerInputComponent);
DECLARE_DELEGATE_OneParam(FActionKeyDelegate, bool)
// Bind jump events
PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);
// Bind fire event
PlayerInputComponent->BindAction("PrimaryAction", IE_Pressed, this, &AFPSurvivalCharacter::OnPrimaryAction);
// Bind Run event
PlayerInputComponent->BindAction<FActionKeyDelegate>("Sprint", IE_Pressed, this, &AFPSurvivalCharacter::OnSprintAction, true);
PlayerInputComponent->BindAction<FActionKeyDelegate>("Sprint", IE_Released, this, &AFPSurvivalCharacter::OnSprintAction, false);
PlayerInputComponent->BindAction<FActionKeyDelegate>("Crouch", IE_Pressed, this, &AFPSurvivalCharacter::OnCrouchAction, true);
PlayerInputComponent->BindAction<FActionKeyDelegate>("Crouch", IE_Released, this, &AFPSurvivalCharacter::OnCrouchAction, false);
// Enable touchscreen input
EnableTouchscreenMovement(PlayerInputComponent);
// Bind movement events
PlayerInputComponent->BindAxis("Move Forward / Backward", this, &AFPSurvivalCharacter::MoveForward);
PlayerInputComponent->BindAxis("Move Right / Left", this, &AFPSurvivalCharacter::MoveRight);
// We have 2 versions of the rotation bindings to handle different kinds of devices differently
// "Mouse" versions handle devices that provide an absolute delta, such as a mouse.
// "Gamepad" versions are for devices that we choose to treat as a rate of change, such as an analog joystick
PlayerInputComponent->BindAxis("Turn Right / Left Mouse", this, &APawn::AddControllerYawInput);
PlayerInputComponent->BindAxis("Look Up / Down Mouse", this, &APawn::AddControllerPitchInput);
PlayerInputComponent->BindAxis("Turn Right / Left Gamepad", this, &AFPSurvivalCharacter::TurnAtRate);
PlayerInputComponent->BindAxis("Look Up / Down Gamepad", this, &AFPSurvivalCharacter::LookUpAtRate);
}
void AFPSurvivalCharacter::SmoothCrouchInterpolateReturn(float Value)
{
const float CrouchHeight = GetCharacterMovement()->GetCrouchedHalfHeight();
const auto LerpHeight = FMath::Lerp(CrouchHeight, StandingCapsuleHalfHeight, Value);
GetCapsuleComponent()->SetCapsuleHalfHeight(LerpHeight);
const auto RelativeLocation = FirstPersonCameraComponent->GetRelativeLocation();
FirstPersonCameraComponent->SetRelativeLocation(FVector(RelativeLocation.X, RelativeLocation.Y, (FMath::Lerp(CrouchHeight, RelativeLocation.Z, Value))));
}
void AFPSurvivalCharacter::SmoothCrouchOnFinish()
{
}
//void AFPSurvivalCharacter::SlideTimelineReturn(float Value)
//{
//}
void AFPSurvivalCharacter::OnPrimaryAction()
{
// Trigger the OnItemUsed Event
OnUseItem.Broadcast();
}
bool AFPSurvivalCharacter::CanStand()
{
if(ButtonPressed["Crouch"])
{
return true;
}
const auto Location = GetActorLocation();
const FVector Feet = FVector(Location.X, Location.Y, Location.Z - GetCapsuleComponent()->GetScaledCapsuleHalfHeight());
const FVector Head = FVector(Feet.X, Feet.Y, Feet.Z + StandingCapsuleHalfHeight * 2);
FHitResult HitResult;
GetWorld()->LineTraceSingleByChannel(HitResult, Feet, Head, ECC_Visibility);
return !HitResult.bBlockingHit;
}
bool AFPSurvivalCharacter::CanSprint()
{
if(ButtonPressed["Sprint"])
{
return !GetCharacterMovement()->IsFalling() && CanStand();
}
return false;
}
void AFPSurvivalCharacter::BeginSlide()
{
BeginCameraTilt();
}
void AFPSurvivalCharacter::EndSlide()
{
EndCameraTilt();
}
void AFPSurvivalCharacter::BeginCameraTilt()
{
}
void AFPSurvivalCharacter::EndCameraTilt()
{
}
void AFPSurvivalCharacter::BeginTouch(const ETouchIndex::Type FingerIndex, const FVector Location)
{
if (TouchItem.bIsPressed == true)
{
return;
}
if ((FingerIndex == TouchItem.FingerIndex) && (TouchItem.bMoved == false))
{
OnPrimaryAction();
}
TouchItem.bIsPressed = true;
TouchItem.FingerIndex = FingerIndex;
TouchItem.Location = Location;
TouchItem.bMoved = false;
}
void AFPSurvivalCharacter::EndTouch(const ETouchIndex::Type FingerIndex, const FVector Location)
{
if (TouchItem.bIsPressed == false)
{
return;
}
TouchItem.bIsPressed = false;
}
void AFPSurvivalCharacter::OnSprintAction(const bool Pressed)
{
if(Pressed)
{
ButtonPressed["Sprint"] = true;
if(MovementState == EMovementState::Walking && CanStand())
SetMovementState(EMovementState::Sprinting);
}
else
{
ButtonPressed["Sprint"] = false;
if(MovementState == EMovementState::Sprinting)
ResolveMovementState();
}
}
void AFPSurvivalCharacter::OnCrouchAction(const bool Pressed)
{
if(Pressed)
{
ButtonPressed["Crouch"] = true;
if(MovementState == EMovementState::Walking)
{
SetMovementState(EMovementState::Crouching);
SmoothCrouchingCurveTimeline->Play();
}
if(MovementState == EMovementState::Sprinting)
{
SetMovementState(EMovementState::Sliding);
}
}
else
{
ButtonPressed["Crouch"] = false;
ResolveMovementState();
}
}
void AFPSurvivalCharacter::SetMovementState(const EMovementState NewMovementState)
{
if(NewMovementState != MovementState)
{
PrevMovementState = MovementState;
MovementState = NewMovementState;
OnMovementStateChanged();
}
}
void AFPSurvivalCharacter::ResolveMovementState()
{
if(CanStand())
{
SmoothCrouchingCurveTimeline->Reverse();
if(CanSprint())
{
if(GEngine)
{
GEngine->AddOnScreenDebugMessage(-1, 3.0f, FColor::Blue, TEXT("앉기 중 달리기"));
}
SetMovementState(EMovementState::Sprinting);
}
else
{
SetMovementState(EMovementState::Walking);
}
}
else
{
SetMovementState(EMovementState::Crouching);
}
}
void AFPSurvivalCharacter::OnMovementStateChanged()
{
if(SpeedMap[MovementState] != NULL)
GetCharacterMovement()->MaxWalkSpeed = SpeedMap[MovementState];
}
void AFPSurvivalCharacter::MoveForward(float Value)
{
if (Value != 0.0f)
{
// add movement in that direction
AddMovementInput(GetActorForwardVector(), Value);
}
}
void AFPSurvivalCharacter::MoveRight(float Value)
{
if (Value != 0.0f)
{
// add movement in that direction
AddMovementInput(GetActorRightVector(), Value);
}
}
void AFPSurvivalCharacter::TurnAtRate(float Rate)
{
// calculate delta for this frame from the rate information
AddControllerYawInput(Rate * TurnRateGamepad * GetWorld()->GetDeltaSeconds());
}
void AFPSurvivalCharacter::LookUpAtRate(float Rate)
{
// calculate delta for this frame from the rate information
AddControllerPitchInput(Rate * TurnRateGamepad * GetWorld()->GetDeltaSeconds());
}
bool AFPSurvivalCharacter::EnableTouchscreenMovement(class UInputComponent* PlayerInputComponent)
{
if (FPlatformMisc::SupportsTouchInput() || GetDefault<UInputSettings>()->bUseMouseForTouch)
{
PlayerInputComponent->BindTouch(EInputEvent::IE_Pressed, this, &AFPSurvivalCharacter::BeginTouch);
PlayerInputComponent->BindTouch(EInputEvent::IE_Released, this, &AFPSurvivalCharacter::EndTouch);
return true;
}
return false;
}