I am trying to implement first person animation for my game (using anim sequencers), playing in editor was fine, but after building project I got this
I have no idea of how to fix it,
(P.S, I reimported & re-checked all animation sequencers, skeletons, all assets are vaild :/, Also tried to delete binaries, intermediate, saving and other folders to regenerate project - it won’t help)
Here’s the code of Player, one of the item (just for example) and interface
"
#include "PlayerCharacter.h"
#include "Engine/Engine.h"
#include "Components/CapsuleComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "PlayerCharacterInterface.h"
#include "AbstractItemActor.h"
#include "InventoryComponent.h"
#include "PlayerCharacterHUD.h"
#include "Kismet/GameplayStatics.h"
#include "Containers/UnrealString.h"
#include "BagOfCoinsItemActor.h"
#include "ViewModelInterface.h"
#include "Camera/CameraComponent.h"
// Sets default values
APlayerCharacter::APlayerCharacter()
{
// Set this character to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = false;
MaxHealth = 100;
MaxMana = 100;
MaxLevel = 10;
MaxExperience = INT64_MAX;
MaxStrenght = 10;
MaxAgility = 10;
MaxIntelligence = 10;
Health = MaxHealth;
Mana = MaxMana;
Level = 0;
Experience = 0;
Strenght = 1;
Agility = 1;
Intelligence = 1;
Money = 0;
MaxMoney= INT64_MAX;
WalkSpeed = 250.0f;
RunSpeed = 500.0f;
GetCapsuleComponent()->InitCapsuleSize(55.f, 96.0f);
RootComponent = GetCapsuleComponent();
GetCharacterMovement()->MaxWalkSpeed = WalkSpeed;
GetCharacterMovement()->JumpZVelocity = 600.0f;
GetCharacterMovement()->GravityScale = 2.0f;
GetCharacterMovement()->GroundFriction = 8.0f;
GetCharacterMovement()->BrakingDecelerationWalking = 800.0f;
GetCharacterMovement()->CrouchedHalfHeight = 40.0f;
GetCharacterMovement()->MaxWalkSpeedCrouched = 125.0f;
GetCharacterMovement()->AirControl = 0.5f;
FirstPersonCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FirstPersonCamera"));
InventoryComponent = CreateDefaultSubobject<UInventoryComponent>(TEXT("InventoryComponent"));
WorldModel = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("WorldModel"));
PickUpSound = CreateDefaultSubobject<USoundBase>(TEXT("PickUpSound"));
WorldModel->SetupAttachment(GetCapsuleComponent());
WorldModel->SetRelativeLocation(FVector(0.0f, 0.0f, GetCapsuleComponent()->GetScaledCapsuleHalfHeight()));
WorldModel->SetRelativeRotation(FRotator(0.0f, 0.0f, 0.0f));
EquippedArmsModel = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("EquipedArmsModel"));
EquippedItemModel = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("EquipedItemModel"));
EquippedArmsModel->SetupAttachment(GetCapsuleComponent());
EquippedArmsModel->SetAnimationMode(EAnimationMode::AnimationSingleNode);
EquippedItemModel->SetAnimationMode(EAnimationMode::AnimationSingleNode);
FirstPersonCamera->SetupAttachment(GetCapsuleComponent()); // Position the camera
EquippedArmsModel->PrimaryComponentTick.bCanEverTick = true;
EquippedItemModel->PrimaryComponentTick.bCanEverTick = true;
FirstPersonCamera->bUsePawnControlRotation = true;
}
// Called when the game starts or when spawned
void APlayerCharacter::BeginPlay()
{
Super::BeginPlay();
FAttachmentTransformRules AttachRules(EAttachmentRule::SnapToTarget, EAttachmentRule::SnapToTarget, EAttachmentRule::KeepWorld,false);
EquippedItemModel->AttachToComponent(EquippedArmsModel, AttachRules, TEXT("I"));
EquippedArmsModel->SetVisibility(false);
EquippedItemModel->SetVisibility(false);
UnequipItem();
APlayerController* PlayerController = Cast<APlayerController>(GetController());
APlayerCharacterHUD* PlayerCharacterHUD = Cast<APlayerCharacterHUD>(PlayerController->GetHUD());
}
void APlayerCharacter::MoveForward(float val)
{
if (val != 0.0f)
{
AddMovementInput(GetActorForwardVector(), val);
}
}
void APlayerCharacter::MoveRight(float val)
{
if (val != 0.0f)
{
AddMovementInput(GetActorRightVector(), val);
}
}
void APlayerCharacter::Run()
{
GetCharacterMovement()->MaxWalkSpeed = RunSpeed;
}
void APlayerCharacter::StopRun()
{
GetCharacterMovement()->MaxWalkSpeed = WalkSpeed;
}
void APlayerCharacter::DebugPrintInv()
{
if (InventoryComponent)
{
InventoryComponent->PrintInventory();
}
}
// Called every frame
void APlayerCharacter::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
// Called to bind functionality to input
void APlayerCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
Super::SetupPlayerInputComponent(PlayerInputComponent);
PlayerInputComponent->BindAction("UseItem", IE_Pressed, this, &APlayerCharacter::UseItem);
PlayerInputComponent->BindAction("DropItem", IE_Pressed, this, &APlayerCharacter::DropEquipedItem);
PlayerInputComponent->BindAction("UnequipItem", IE_Pressed, this, &APlayerCharacter::UnequipItem);
PlayerInputComponent->BindAction("ShowInventory", IE_Pressed, this, &APlayerCharacter::ToggleInventory);
PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &APlayerCharacter::DebugPrintInv);
PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);
PlayerInputComponent->BindAction("Run", IE_Pressed, this, &APlayerCharacter::Run);
PlayerInputComponent->BindAction("Run", IE_Released, this, &APlayerCharacter::StopRun);
PlayerInputComponent->BindAction("Interact", IE_Pressed, this, &APlayerCharacter::Interact);
PlayerInputComponent->BindAxis("Look", this, &APawn::AddControllerYawInput);
PlayerInputComponent->BindAxis("Turn", this, &APawn::AddControllerPitchInput);
PlayerInputComponent->BindAxis("Walk",this,&APlayerCharacter::MoveForward);
PlayerInputComponent->BindAxis("Strafe",this,&APlayerCharacter::MoveRight);
}
uint8 APlayerCharacter::GetHealth()
{
return Health;
}
uint8 APlayerCharacter::GetMana()
{
return Mana;
}
uint8 APlayerCharacter::GetLevel()
{
return Level;
}
int64 APlayerCharacter::GetExperience()
{
return Experience;
}
uint8 APlayerCharacter::GetStrenght()
{
return Strenght;
}
uint8 APlayerCharacter::GetAgility()
{
return Agility;
}
uint8 APlayerCharacter::GetIntelligence()
{
return Intelligence;
}
void APlayerCharacter::SetHealth(uint8 _health)
{
Health = _health;
if (Health >= MaxHealth) Health = MaxHealth;
if (Health <= 0) Health = 0;
}
void APlayerCharacter::SetMana(uint8 _mana)
{
Mana = _mana;
if (Mana >= MaxMana) Mana = MaxMana;
if (Mana <= 0) Mana = 0;
}
void APlayerCharacter::SetLevel(uint8 _level)
{
Level = _level;
}
void APlayerCharacter::SetExperience(int64 _experience)
{
Experience = _experience;
}
void APlayerCharacter::SetStrenght(uint8 _strenght)
{
Strenght = _strenght;
}
void APlayerCharacter::SetAgility(uint8 _agility)
{
Agility = _agility;
}
void APlayerCharacter::SetIntelligence(uint8 _intelligence)
{
Intelligence = _intelligence;
}
int64 APlayerCharacter::GetMoney()
{
return Money;
}
FVector APlayerCharacter::GetGameObjectLocation()
{
return GetActorLocation();
}
FRotator APlayerCharacter::GetGameObjectRotation()
{
return GetActorRotation();
}
UInventoryComponent* APlayerCharacter::GetInventory()
{
return InventoryComponent;
}
void APlayerCharacter::Interact()
{
FHitResult Hit;
FVector TraceStart = this->FirstPersonCamera->GetComponentLocation();
FVector TraceEnd = TraceStart + (this->FirstPersonCamera->GetForwardVector() * 200.0f);
FCollisionQueryParams QueryParams;
QueryParams.AddIgnoredActor(this);
bool bHit = GetWorld()->LineTraceSingleByChannel(Hit, TraceStart, TraceEnd, ECC_Visibility, QueryParams);
DrawDebugLine(GetWorld(), TraceStart, TraceEnd, Hit.bBlockingHit ? FColor::Blue : FColor::Red, false, 1.0f, 0, 1.0f);
if (AAbstractItemActor* HitItem = Cast<AAbstractItemActor>(Hit.GetActor()))
{
UGameplayStatics::PlaySoundAtLocation(this, PickUpSound, this->GetActorLocation());
if (HitItem->IsA(ABagOfCoinsItemActor::StaticClass()))
{
IItemInterface* ItemInterface = Cast<IItemInterface>(HitItem);
{
ItemInterface->UseItem();
}
}
else
{
if (HitItem->CurrentItemAmount >= 1) InventoryComponent->AddItem(HitItem);
}
}
}
void APlayerCharacter::ToggleInventory()
{
if (APlayerController* PlayerController = Cast<APlayerController>(GetController()))
{
if (APlayerCharacterHUD* PlayerCharacterHUD = Cast<APlayerCharacterHUD>(PlayerController->GetHUD()))
{
PlayerCharacterHUD->ToggleInventory(InventoryComponent);
}
}
}
bool APlayerCharacter::bIsItemEquiped()
{
if (ItemEquiped != nullptr)
{
return true;
}
return false;
}
void APlayerCharacter::UpdateUI()
{
if (APlayerController* PlayerController = Cast<APlayerController>(GetController()))
{
if (APlayerCharacterHUD* PlayerCharacterHUD = Cast<APlayerCharacterHUD>(PlayerController->GetHUD()))
{
PlayerCharacterHUD->UpdateInventoryUI(InventoryComponent);
}
}
}
AAbstractItemActor* APlayerCharacter::GetEqupiedItem()
{
return ItemEquiped;
}
void APlayerCharacter::SetMoney(int64 _money)
{
Money = _money;
}
void APlayerCharacter::ReturnToIdleAnim()
{
if (IViewModelInterface* ViewModel = Cast<IViewModelInterface>(ItemEquiped))
{
if (ItemEquiped && ItemEquiped > 0)
{
EquippedArmsModel->SetVisibility(true);
EquippedItemModel->SetVisibility(true);
UAnimSequence* ArmsAnim = ViewModel->GetAnimSequenceAtIndex(0);
UAnimSequence* ItemAnim = ViewModel->GetAnimSequenceAtIndex(1);
if (ArmsAnim && ItemAnim)
{
EquippedArmsModel->PlayAnimation(ArmsAnim, true);
EquippedItemModel->PlayAnimation(ItemAnim, true);
}
}
else
{
UnequipItem();
}
}
GetWorld()->GetTimerManager().ClearTimer(UseAnimationTimerHandle);
}
void APlayerCharacter::UseItem()
{
if (ItemEquiped)
{
UE_LOG(LogTemp, Warning, TEXT("Using Equiped Item"));
if (IItemInterface* Item = Cast<IItemInterface>(ItemEquiped))
{
if (IViewModelInterface* ViewModel = Cast<IViewModelInterface>(Item))
{
if (GetWorld()->GetTimerManager().IsTimerActive(UseAnimationTimerHandle))
{
UE_LOG(LogTemp, Warning, TEXT("Item use already in progress!"));
return;
}
EquippedArmsModel->SetVisibility(true);
EquippedItemModel->SetVisibility(true);
UAnimSequence* ArmsModel = ViewModel->GetAnimSequenceAtIndex(2);
UAnimSequence* ItemModel = ViewModel->GetAnimSequenceAtIndex(3);
if (ArmsModel && ItemModel)
{
EquippedArmsModel->PlayAnimation(ArmsModel, true);
EquippedItemModel->PlayAnimation(ItemModel, true);
}
float AnimationDuration = ViewModel->GetAnimSequenceAtIndex(2)->GetPlayLength();
GetWorld()->GetTimerManager().SetTimer(UseAnimationTimerHandle,this,&APlayerCharacter::ReturnToIdleAnim,AnimationDuration,false);
Item->UseItem();
GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Yellow, FString::Printf(TEXT("\tItem Amount: %d"), ItemEquiped->CurrentItemAmount));
}
}
if (ItemEquiped->CurrentItemAmount <= 0)
{
UnequipItem();
}
}
else
{
UE_LOG(LogTemp, Warning, TEXT("No Item to Use!"));
return;
}
//UpdateUI();
}
void APlayerCharacter::DropEquipedItem()
{
if (!ItemEquiped) return;
if (ItemEquiped->CurrentItemAmount <= 0)
{
ItemEquiped->SetActorHiddenInGame(true);
ItemEquiped->SetActorEnableCollision(false);
ItemEquiped->SetLifeSpan(1.0f);
ItemEquiped = nullptr;
return;
}
FVector TraceStart = FirstPersonCamera->GetComponentLocation();
FVector TraceEnd = TraceStart + (FirstPersonCamera->GetForwardVector() * 100.0f);
FHitResult Hit;
FCollisionQueryParams QueryParams;
QueryParams.AddIgnoredActor(this);
FVector SpawnLocation = TraceEnd;
if (GetWorld()->LineTraceSingleByChannel(Hit, TraceStart, TraceEnd, ECC_Visibility, QueryParams))
{
SpawnLocation = Hit.Location + Hit.Normal * 10.0f;
}
ItemEquiped->DetachFromActor(FDetachmentTransformRules::KeepRelativeTransform);
ItemEquiped->SetActorLocation(SpawnLocation);
ItemEquiped->SetActorScale3D(ItemEquiped->WorldModelScale);
ItemEquiped->GetWorldModel()->SetSimulatePhysics(true);
ItemEquiped = nullptr;
UE_LOG(LogTemp, Display, TEXT("Dropped equipped item."));
}
void APlayerCharacter::EquipItem(AAbstractItemActor* Item)
{
if (!Item || !InventoryComponent || !EquippedArmsModel || !EquippedItemModel)
{
UE_LOG(LogTemp, Warning, TEXT("EquipItem failed: Invalid item or missing inventory."));
return;
}
/*
if (ItemEquiped && !ItemEquiped->IsPendingKill() &&
ItemEquiped->CurrentItemAmount > 0)
{
UE_LOG(LogTemp, Warning, TEXT("EquipItem blocked: already holding an item."));
return;
}
// Spawn a copy of the item actor for visual representation
FActorSpawnParameters SpawnParams;
SpawnParams.SpawnCollisionHandlingOverride = ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
AAbstractItemActor* SpawnedItem = GetWorld()->SpawnActor<AAbstractItemActor>(
Item->GetClass(),
FTransform::Identity,
SpawnParams
);
if (!SpawnedItem)
{
UE_LOG(LogTemp, Error, TEXT("EquipItem failed: Could not spawn item actor."));
return;
}
// Set visual/logic state of the item
SpawnedItem->CurrentItemAmount = (Item->CurrentItemAmount);
if (SpawnedItem->CurrentItemAmount <= 0)
{
SpawnedItem->SetActorHiddenInGame(true);
SpawnedItem->SetActorEnableCollision(false);
SpawnedItem->SetLifeSpan(1.0f);
}
// Disable physics and attach to the player model (e.g., hand socket)
SpawnedItem->DisableComponentsSimulatePhysics();
FAttachmentTransformRules AttachRules(EAttachmentRule::SnapToTarget, true);
SpawnedItem->AttachToComponent(WorldModel, AttachRules, ItemSocketName);
SpawnedItem->SetActorRelativeTransform(Item->GetFirstPersonTranform());*/
ItemEquiped = Item;
if (IViewModelInterface* ViewModel = Cast<IViewModelInterface>(Item))
{
for (int32 i = 0; i < ItemEquiped->WorldModelMaterials.Num(); i++)
{
EquippedItemModel->SetMaterial(i, ItemEquiped->WorldModelMaterials[i]);
}
EquippedArmsModel->SetVisibility(true);
EquippedItemModel->SetVisibility(true);
UAnimSequence* IdleArms = ViewModel->GetAnimSequenceAtIndex(0);
UAnimSequence* IdleItem = ViewModel->GetAnimSequenceAtIndex(1);
if (IdleArms && IdleItem)
{
EquippedArmsModel->PlayAnimation(IdleArms, true);
EquippedItemModel->PlayAnimation(IdleItem, true);
}
}
// Remove from inventory (using reference-safe method)
if (InventoryComponent->GetItems().Contains(Item)) // Optional helper
{
InventoryComponent->RemoveItem(Item);
}
UpdateUI();
//UE_LOG(LogTemp, Display, TEXT("Equipped item: %s"), TEXT)*SpawnedItem->ItemName.ToString);
}
void APlayerCharacter::UnequipItem()
{
if (ItemEquiped)
{
uint8 Amount = ItemEquiped->CurrentItemAmount;
AAbstractItemActor* Clone = ItemEquiped;
if (Clone && Amount > 0)
{
InventoryComponent->AddItem(Clone);
}
ItemEquiped->SetActorHiddenInGame(true);
ItemEquiped->SetActorEnableCollision(false);
ItemEquiped->SetLifeSpan(1.0f);
EquippedArmsModel->SetVisibility(false);
EquippedItemModel->SetVisibility(false);
ItemEquiped = nullptr;
}
}
"
#include "SmallManaPotiontemActor.h"
#include "Kismet/GameplayStatics.h"
#include "PlayerCharacter.h"
#include "PlayerCharacterInterface.h"
#include "Engine/Engine.h"
ASmallManaPotiontemActor::ASmallManaPotiontemActor()
{
ManaValue = 25;
ItemName = NSLOCTEXT("Default", "ItemName", "Mana Potion (S)");
ItemDescription = FText::Format(NSLOCTEXT("Default", "ItemName", "Restores your mana a bit (+{0} mana)"), ManaValue);
CurrentItemAmount = 1;
MaxItemAmount = 8;
static ConstructorHelpers::FObjectFinder<USlateBrushAsset> IconFinder(TEXT("/Game/ModelsAndTextures/Textures/Icons/SlateBrushes/SmallManaPotionBrush"));
if (IconFinder.Succeeded())
{
this->ItemIcon = IconFinder.Object;
}
static ConstructorHelpers::FObjectFinder<UStaticMesh> MeshFinder(TEXT("/Game/ModelsAndTextures/Models/Potions/SmallManaPotion")); // Replace with your mesh path
if (MeshFinder.Succeeded())
{
WorldModel->SetStaticMesh(MeshFinder.Object);
}
WorldModel->SetRelativeScale3D(FVector(0.12f, 0.12f, 0.12f));
GetFirstPersonTranform().SetScale3D(FVector(0.1, 0.1, 0.1));
ConsumeSound = CreateDefaultSubobject<USoundBase>(TEXT("ConsumeSound"));
}
void ASmallManaPotiontemActor::UseItem()
{
UE_LOG(LogTemp, Warning, TEXT("Using Small Mana Potion"));
AActor* Player = UGameplayStatics::GetActorOfClass(GetWorld(), APlayerCharacter::StaticClass());
if (Player)
{
if (IPlayerCharacterInterface* PlayerInterface = Cast<IPlayerCharacterInterface>(Player))
{
PlayerInterface->SetMana(PlayerInterface->GetMana() + ManaValue);
DecrementItemAmount();
if (this->CurrentItemAmount <= 0)
{
this->SetActorHiddenInGame(true);
this->SetActorEnableCollision(false);
this->SetLifeSpan(1.0f);
}
}
}
}
uint8 ASmallManaPotiontemActor::GetManaValue()
{
return ManaValue;
}
void ASmallManaPotiontemActor::SetManaValue(uint8 _manavalue)
{
ManaValue = _manavalue;
}
USoundBase* ASmallManaPotiontemActor::GetSound()
{
return ConsumeSound;
}
#include "CoreMinimal.h"
#include "UObject/Interface.h"
#include "ViewModelInterface.generated.h"
// This class does not need to be modified.
UINTERFACE(MinimalAPI)
class UViewModelInterface : public UInterface
{
GENERATED_BODY()
};
class RPGGAME_API IViewModelInterface
{
GENERATED_BODY()
// Add interface functions to this class. This is the class that will be inherited to implement this interface.
public:
virtual UAnimSequence* GetAnimSequenceAtIndex(uint8 AnimIndex) = 0;
};