μΊλ¦ν°μ μ₯μ°© κ°λ₯ν μμ΄ν μ νλν ν μ°©μ©νλ κ²μ ꡬνν κ²μ΄λ€.
1. μμ΄ν μμ±
μ¬λ¬ μ’ λ₯μ μμ΄ν μ κ΄λ¦¬ν Base C++ Classλ₯Ό μμ±νλ€. μ΄ ν΄λμ€μμ νμ , λ 벨, λ¨Έν°λ¦¬μΌ, μ½λ¦¬μ λ± κ³΅ν΅μΌλ‘ μ¬μ©λ κΈ°λ₯λ€μ κ΄λ¦¬νλ€. κ° μμ΄ν λ§λ€ λ€λ₯΄κ² ꡬνλμ΄μΌ νλ κ²(μ€νν± λ©μ λ±)λ€μ λΈλ£¨νλ¦°νΈ ν΄λμ€λ₯Ό μμ±νμ¬ κ·Έ μμμ κ΄λ¦¬λλλ‘ λ°©ν₯μ μ‘μλ€.
μμ΄ν λ§λ€ νμ μ΄ λ€λ₯΄κ³ , κ°μ νμ μ μμ΄ν μ΄λΌλ λ λ²¨μ΄ λ€λ₯΄κΈ° λλ¬Έμ νμ κ³Ό λ 벨μ μ μΈνλ€.
UENUM(BlueprintType)
enum class EItemType : uint8
{
HAT,
BAG,
KEY,
GADGET,
MAX
};
UPROPERTY(EditAnywhere)
EItemType Type = EItemType::HAT;
UPROPERTY()
int Level = 1;
κ·Έ μΈμλ μ€νν± λ©μμ μ½λ¦¬μ λ μΆκ°νλ€.
UPROPERTY(EditAnywhere)
UStaticMeshComponent* StaticMesh;
UPROPERTY(EditAnywhere)
UBoxComponent* CollisionBox;
UFUNCTION()
void OnBeginOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
UFUNCTION()
void OnEndOverlap(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor, class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
AItem::AItem()
{
CollisionBox = CreateDefaultSubobject<UBoxComponent>(TEXT("BoxComponent"));
RootComponent = CollisionBox;
CollisionBox->SetBoxExtent(FVector(15, 15, 15));
CollisionBox->SetCollisionProfileName(TEXT("OverlapOnlySurvivor"));
CollisionBox->OnComponentBeginOverlap.AddDynamic(this, &AItem::OnBeginOverlap);
CollisionBox->OnComponentEndOverlap.AddDynamic(this, &AItem::OnEndOverlap);
StaticMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("ItemMesh"));
StaticMesh->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
StaticMesh->SetCollisionProfileName(TEXT("NoCollision"));
StaticMesh->bReceivesDecals = false;
}
- μ½λ¦¬μ μ OverlapOnlySurvivorμ 컀μ€ν μ½λ¦¬μ ν리μ μΌλ‘ μ€μ§ μΊλ¦ν°μλ§ Overlap λ°μμ νλ€.
- μ€νν± λ©μλ μμ±μμμ μ»΄ν¬λνΈ μμ±λ§ νκ³ μμ΄ λΈλ£¨νλ¦°νΈ ν΄λμ€μμ μΆκ° μ€μ μ΄ νμνλ€.
- μμ±μμμ μ½λ¦¬μ μ»΄ν¬λνΈ μμ± μ μ¬μ΄μ¦λ₯Ό μ€μ νμ§λ§, κ° μμ΄ν λ§λ€ ν¬κΈ°κ° λ€λ₯Ό μ μμΌλ―λ‘ λΈλ£¨νλ¦°νΈ ν΄λμ€μμ μΆκ°λ‘ μ€νν± λ©μμ λ§κ² μμ μ΄ νμνλ€.
2. μμ΄ν νλ
μΊλ¦ν°μ μμ΄ν μ΄ μΆ©λνλ©΄ μμ΄ν μ μΊλ¦ν° λ΄ InventoryComponentμ λκΈ΄λ€. μ¬λ¬ κ°μ μμ΄ν κ³Ό μΆ©λλ κ°λ₯μ±μ΄ μκΈ° λλ¬Έμ InventoryComponent λ΄μμ μμλ₯Ό κ΄λ¦¬νκΈ° μν΄ μ΄λ¬ν κ΅¬μ‘°λ‘ κ΅¬ννλ€.
void AItem::OnBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
ASurvivorCharacter* OtherCharacter = Cast<ASurvivorCharacter>(OtherActor);
if (OtherCharacter)
{
OtherCharacter->InventoryComponent->BeginOverlap(this);
}
}
void AItem::OnEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex)
{
ASurvivorCharacter* OtherCharacter = Cast<ASurvivorCharacter>(OtherActor);
if (OtherCharacter)
{
OtherCharacter->InventoryComponent->EndOverlap(this);
}
}
μ΄λ κ² λ°μ μμ΄ν μ InventoryComponentμ PickItemArrayμ μ μ₯ν ν, μΊλ¦ν°κ° νλ λ²νΌμ λλ₯΄λ©΄ κ°μ₯ λ¨Όμ μ μ₯λ μμ΄ν μ΄ νλλκ² λλ€.
void UInventoryComponent::BeginOverlap(AItem* Item)
{
PickItemArray.Add(Item);
}
void UInventoryComponent::EndOverlap(AItem* Item)
{
PickItemArray.Remove(Item);
}
bool UInventoryComponent::Input()
{
bool Pick = false;
if (PickItemArray.Num() > 0)
{
AItem* OverlapItem = PickItemArray[0];
...
if (Pick)
{
PickItemArray.RemoveAt(0);
OverlapItem->Destroy();
}
}
return Pick;
}
μ΄μ μμ΄ν νλ μ λ ₯ ꡬνμ΄ νμνλ€. μΊλ¦ν° μ λ ₯μ μ΄λ―Έ ν₯μλ μ λ ₯μ μ¬μ©νμ¬ κ΅¬νλμ΄ μκΈ° λλ¬Έμ μ¬κΈ°μ μμ΄ν νλ μ λ ₯ μ‘μ λ§ μΆκ°ν κ²μ΄λ€.
μμ΄ν νλ μ λ ₯ μ‘μ μ ν€λ₯Ό λλ λμ§ μ¬λΆλ§ νμν΄μ bool νμ μΌλ‘ μ€μ νλ€.
μμ±ν μ λ ₯ μ‘μ μ μΊλ¦ν°μ μ μ©ν κ²μ΄λ€. νλ μ λ ₯μ΄ λ€μ΄μ€λ©΄, μΊλ¦ν°μ λ μ μμκ±°λ κ±·κ³ μλ μνμΈμ§ 체ν¬νλ€. νλ κ°λ₯ν μνλΌλ©΄ InventoryComponentμ Input() ν¨μλ₯Ό νΈμΆνκ³ μ μμ μΌλ‘ νλμ΄ λμλ€λ©΄ trueλ₯Ό λ°νλ°λλ€. κ·Έ ν μ λλ©μ΄μ μ¬μμ μν΄ μΊλ¦ν° μνλ₯Ό ITEM_PICKλ‘ λ³κ²½νλ€.
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
UInputMappingContext* DefaultMappingContext;
UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Input, meta = (AllowPrivateAccess = "true"))
UInputAction* ItemPickAction;
void ASurvivorCharacter::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
// Set up action bindings
if (UEnhancedInputComponent* EnhancedInputComponent = Cast<UEnhancedInputComponent>(PlayerInputComponent)) {
EnhancedInputComponent->BindAction(LookAction, ETriggerEvent::Triggered, this, &ASurvivorCharacter::Look);
EnhancedInputComponent->BindAction(WalkAction, ETriggerEvent::Triggered, this, &ASurvivorCharacter::Walk);
EnhancedInputComponent->BindAction(RunAction, ETriggerEvent::Started, this, &ASurvivorCharacter::Run);
EnhancedInputComponent->BindAction(RunAction, ETriggerEvent::Completed, this, &ASurvivorCharacter::Run);
EnhancedInputComponent->BindAction(ItemPickAction, ETriggerEvent::Started, this, &ASurvivorCharacter::ItemPick);
...
}
else
{
UE_LOG(LogTemplateCharacter, Error, TEXT("'%s' Failed to find an Enhanced Input component! This template is built to use the Enhanced Input system. If you intend to use the legacy system, then you will need to update this C++ file."), *GetNameSafe(this));
}
}
void ASurvivorCharacter::ItemPick(const FInputActionValue& Value)
{
if (State == ECharacterState::LAND)
{
if (InventoryComponent->Input())
{
SetECharacterState(ECharacterState::ITEM_PICK);
}
}
}
3. μμ΄ν μ₯μ°©
UInventoryComponent λ΄λΆμμ μμ΄ν νλ ν μ₯μ°© μμ΄ν μ΄λ©΄ μΊλ¦ν°μκ² μ₯μ°© μμ²μ νλ€. μΊλ¦ν° λ΄ μμ΄ν λ©μμ Visibleμ νμ±ννκ³ νλν μμ΄ν λ 벨μ λ§κ² Matarialμ λ³κ²½νλ€.
void ASurvivorCharacter::ItemPutOn(EItemType Type, int Level)
{
if (GetItemCount(Type, Level) == 0)
return;
...
if (Type == EItemType::HAT) {
HatMesh->SetVisibility(true);
HatMesh->SetMaterial(0, ItemMaterials[Level - 1]);
}
else if (Type == EItemType::BAG) {
BagMesh->SetVisibility(true);
BagMesh->SetMaterial(0, ItemMaterials[Level - 1]);
...
}
}
μ¬κΈ°μ HatMeshμ BagMeshλ μμΌμ λΆλλ‘ μ€μ μ΄ νμνλ€. κ·ΈλμΌ μΊλ¦ν° μ λλ©μ΄μ μ λ§κ² μμ΄ν λ©μλ μμ§μ΄κ² λλ€.
HatMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("HatMesh"));
HatMesh->SetupAttachment(GetMesh(), FName("Hat"));
HatMesh->SetCollisionProfileName(TEXT("NoCollision"));
HatMesh->SetVisibility(false);
HatMesh->bReceivesDecals = false;
BagMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BagMesh"));
BagMesh->SetupAttachment(GetMesh(), FName("Bag"));
BagMesh->SetCollisionProfileName(TEXT("NoCollision"));
BagMesh->SetVisibility(false);
BagMesh->bReceivesDecals = false;
μμ΄ν κ·Όμ²μμ ν€λ₯Ό λλ₯΄λ©΄ ν΄λΉ μμ΄ν μ μ°©μ©νλ€.