6. 아이템 종류 추가
A. 에셋 추가


기존 에셋만으로는 내가 생각한 모든 아이템 모습을 만들 수 없어서 Fab에서 무료 에셋을 더 가져왔다.

어제 만든 아이템 블루프린트 액터를 복제한다. 복제한 액터의 이름은 새로 추가한 에셋에 어울리는 이름으로 바꾼다. 기존 액터의 이름도 모습에 맞게 FirstAid라고 바꿨다.


각각 액터 편집화면에서 스태틱 메시를 변경한다. 기존 구급약 메시와 크기가 달라 스케일을 변경했다.

맵에 배치해보니 크기가 적절했다.
다만 해골 마스크 에셋의 색깔은 보라색이 어울릴것 같아서 이 에셋의 머티리얼을 수정했다.


B. 구분하기

새로 추가한 아이템들이 모두 같은 코드를 쓰고 있어서 구분이 안된다. 그렇다고 새로 코드를 만드는 것은 좋은 방법이 아니다.
구분하는 방법은 여러가지 있는데 내가 생각한 방법은 다음과 같다.
private:
//아이템 번호
UPROPERTY(EditDefaultOnly, Category="Item", meta = (AllowPrivateAccess=true))
int itemID;
아이템 액터 헤더에 번호를 입력받을 변수를 추가한다. 이 번호를 통해 구분할 것이다. 이 변수에 값을 넣는 것은 블루프린트를 통해 할 것이니 UPROPERTY에 EditDefaultOnly나 EditAnywhere중 하나를 추가한다.
void AItemActor::OnCharacterOverlap(UPrimitiveComponent* overlappedComp, AActor* otherActor, UPrimitiveComponent* otherComp, int otherBodyIndex, bool fromSweep, const FHitResult& sweepResult)
{
switch (itemID)
{
case 1:
UE_LOG(LogTemp, Warning, TEXT("Coin"));
break;
case 2:
UE_LOG(LogTemp, Warning, TEXT("Skull"));
break;
case 3:
UE_LOG(LogTemp, Warning, TEXT("First Aid"));
break;
default:
UE_LOG(LogTemp, Warning, TEXT("WTF?"));
break;
}
Destroy();
}
캐릭터와 닿아서 사라지기 직전에 생성할 로그는 이 번호를 통해 다른 내용이 나오게 한다.

컴파일을 한 다음 각 아이템 블루프린트를 열면 코드로 선언했던 변수에 값을 넣을 수 있다.

구분이 잘 됨을 확인할 수 있다.
7. 무작위 위치에 아이템 생성하기
이렇게 만들어진 아이템을 일일이 배치하는 것은 귀찮다. 게다가 그냥 직접 배치만 한다면 항상 고정된 위치에 존재한다. 그래서 매 게임 시작마다 다른 위치에 생성되게 만들것이다.

아이템을 무작위 배치를 담당할 액터를 만든다.
//클래스 밖 상단에 선언
#include "ItemActor.h"
//클래스 내부
private:
//동전 아이템
UPROPERTY(EditInstanceOnly, Category = "Item Actor", meta = (AllowPrivateAccess = true))
TSubclassOf<AItemActor> coinItem;
//해골 아이템
UPROPERTY(EditInstanceOnly, Category = "Item Actor", meta = (AllowPrivateAccess = true))
TSubclassOf<AItemActor> skullItem;
//회복 아이템
UPROPERTY(EditInstanceOnly, Category = "Item Actor", meta = (AllowPrivateAccess = true))
TSubclassOf<AItemActor> firstAidItem;
이 액터의 헤더에 3개의 블루프린트를 할당받도록 위와 같이 선언한다. 맵에 배치된 액터가 아니라 그 원본인 블루프린트가 필요하기 때문에 TSubClassof로 선언해야 한다. 그리고 그 블루프린트의 원본인 액터 클래스가 필요하기 때문에 해당 클래스가 있는 해더를 삽입해야 한다.
아이템 배치를 담당할 액터는 블루프린트를 거치지 않고 바로 맵에 배치할 생각이라서 각 변수마다 UPROPERTY에 EditInstanceOnly를 적었다. (EditAnywhere로 바꿔도 동일하게 작동한다.)

해더 삽입시 CoreMinimal.h가 제일 위에, generated 계열 함수가 제일 밑으로 가도록 적어야 하니 유의하자
//ItemManager.h
private:
//아이템 생성
void SpawnItems(int spawnCount);
//ItemManager.cpp
void AItemManager::SpawnItems(int spawnCount)
{
//1개 이상 생성
if (spawnCount <= 0)
return;
for (int iNum = 0; iNum < spawnCount; ++iNum)
{
//무작위 위치
float x = FMath::RandRange(-2000.0f, 2000.0f);
float y = FMath::RandRange(-2000.0f, 2000.0f);
FVector spawnPoint = FVector(x, y, 100.0f);
//해당 위치에 아이템 생성
GetWorld()->SpawnActor<AItemActor>(coinItem, spawnPoint, FRotator::ZeroRotator);
}
}
아이템 생성을 담당할 함수도 선언한다. 매개 변수를 통해 몇 개 만들지를 정하도록 한다.
GetWorld()를 통해 월드 클래스를 가져오면 SpawnActor라는 함수를 사용할 수 있다. 이 함수의 매개변수에 순서대로 액터 클래스, 생성 위치, 회전값을 넣으면 지정한 위치에서 지정한 회전값을 가진 액터를 생성한다.
내가 만든 맵이 가로, 세로 모두 4000 조금 넘길래 -2000 ~ 2000 범위의 무작위 x, y값으로 생성하게 만든다. 회전값은 굳이 건드릴 필요가 없기에 (0,0,0)인 FRotator::ZeroRotator를 사용한다.
그리고 매개변수대로 아이템을 만들어야 하니 for문을 통해 반복하도록 만들었다. (여기서 생성 개수를 잘못 적는 실수에 대비하는 예외 처리도 하는게 좋다.)
void AItemManager::BeginPlay()
{
Super::BeginPlay();
SpawnItems(5);
}
일단은 시작시 5개 생성하도록 한다.

컴파일을 한 다음 액터를 바로 맵에 배치를 한다.

배치된 액터를 선택하고, 디테일 화면에서 각 이름에 맞게 적절한 블루프린트를 할당한다.


실행해보니 아이템이 잘 생성된다. 그리고 매 실행마다 다른 위치에 생성된다.
'언리얼엔진 학습 및 과제' 카테고리의 다른 글
| 게임 루프 및 UI 재설계 과제 (6) (0) | 2025.10.15 |
|---|---|
| 게임 루프 및 UI 재설계 과제 (5) (0) | 2025.10.14 |
| 게임 루프 및 UI 재설계 과제 (3) (0) | 2025.10.01 |
| 게임 루프 및 UI 재설계 과제 (2) (0) | 2025.09.30 |
| 게임 루프 및 UI 재설계 과제 (1) (0) | 2025.09.29 |