Hello!
I am trying to create a “Pick Up” system, that would allow a player to pick up an object and hold it in front of it. I have found some ideas and tried to use them in my project, but the picked up object didn’t move. APlayerCharacter::Interact() and AMyBox::Interact() run, but the box is not attached (at least from the player view) to the socket. I tried to attach the box to the UsceneComponent HeldItem in PlayerCharacter class, but the result was the same.
Edit: changing gravity of the object did not resolve the issue
MyBox cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "MyBox.h"
#include "PlayerCharacter.h"
// Sets default values
AMyBox::AMyBox()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
Root = CreateDefaultSubobject<USceneComponent>("Root");
SetRootComponent(Root);
BoxMesh = CreateDefaultSubobject<UStaticMeshComponent>("Box Mesh");
BoxMesh->SetupAttachment(Root);
bGravity = true;
bHeld = false;
}
// Called when the game starts or when spawned
void AMyBox::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void AMyBox::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void AMyBox::Interact(const APlayerCharacter* HoldingPlayer)
{
if(HoldingPlayer)
{
//this->SetActorEnableCollision(false);
this->AttachToComponent(HoldingPlayer->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, FName("HoverAttachPoint"));
bGravity = false;
bHeld = true;
UE_LOG(LogTemp, Warning, TEXT("Box Interact"));
}
}
Interaction from the Player Character cpp
void APlayerCharacter::Interact()
{
if(HeldItem != nullptr)
Drop();
const FVector Start = CameraComponent->GetComponentLocation();
const FVector End = Start + CameraComponent->GetForwardVector() * InteractionDistance;
FHitResult HitResult;
if(GetWorld()->LineTraceSingleByChannel(HitResult, Start, End, ECC_GameTraceChannel1, Params))
{
UE_LOG(LogTemp, Warning, TEXT("HIT OBJECT NAME: %s"), *HitResult.GetActor()->GetName());
if(APickableActor* PickableItem = Cast<APickableActor>(HitResult.GetActor()))
{
HeldItem = PickableItem;
HeldItem->Interact(this);
}
else if (AInteractiveActor* Item = Cast<AInteractiveActor>(HitResult.GetActor()))
{
Item->ReactToInteraction();
}
}
}
PickableActor cpp (Parent class of MyBox)
// Fill out your copyright notice in the Description page of Project Settings.
#include "PickableActor.h"
#include "PlayerCharacter.h"
// Sets default values
APickableActor::APickableActor()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = true;
bGravity = true;
bHeld = false;
}
// Called when the game starts or when spawned
void APickableActor::BeginPlay()
{
Super::BeginPlay();
}
// Called every frame
void APickableActor::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
void APickableActor::Interact(const APlayerCharacter* HoldingPlayer)
{
if(HoldingPlayer)
{
this->AttachToComponent(HoldingPlayer->GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, FName("HoverAttachPoint"));
bGravity = false;
bHeld = true;
UE_LOG(LogTemp, Warning, TEXT("PickableActor interact"));
}
}
void APickableActor::Drop()
{
bGravity = true;
bHeld = false;
}