* 아래의 책의 내용을 정리한 글입니다! *
오늘은 무기!
일단 아래 에셋 다운로드 해주고
원하는 소켓 우클릭 >> 프리뷰 에셋 추가
적당한위치에 검을 놓아 줍시다!
저는 index_o1_r 에 넣었으나 책에서는 hand_r 에 넣었네요!
여기 넣는다고 넣어지는게 아니라 한번 보는것!
but 소켓의 위치 설정을 해주어야 그대로 검이 붙어가므로 위치설정은 해줍시다!
그다음 코드 추가
ABCharacter.h
UPROPERTY(VisibleAnywhere, Category = Weapon)
USkeletalMeshComponent* Weapon;
ABCharacter.cpp
AABCharacter::AABCharacter(){
//~~~
//무기설정
FName WeaponSocket(TEXT("index_01_r"));
if (GetMesh()->DoesSocketExist(WeaponSocket))
{
Weapon = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("WEAPON"));
static ConstructorHelpers::FObjectFinder<USkeletalMesh> SK_WEAPON(TEXT("/Game/InfinityBladeWeapons/Weapons/Blade/Swords/Blade_BlackKnight/SK_Blade_BlackKnight.SK_Blade_BlackKnight"));
if (SK_WEAPON.Succeeded())
{
Weapon->SetSkeletalMesh(SK_WEAPON.Object);
}
Weapon->SetupAttachment(GetMesh(), WeaponSocket);
}
이제 컴파일 후 보면 검을 쥐고있는 캐릭터가 됩니다!
이렇게 검을 직접 부여해줄수도있지만
무기를 따로 코드로 작성해서 관리하는것도 가능합니다!
그럼 바로 ABWeapon 액터를 만들어 줍시다.
이제 위에 캐릭터에 추가해준 코드를 그대로 아래에도 추가
ABWeapon.h
UPROPERTY(VisibleAnywhere, Category = Weapon)
USkeletalMeshComponent* Weapon;
ABWeapon.cpp
AABWeapon::AABWeapon()
{
// 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;
Weapon = CreateDefaultSubobject<USkeletalMeshComponent>(TEXT("WEAPON"));
RootComponent = Weapon;
static ConstructorHelpers::FObjectFinder<USkeletalMesh> SK_WEAPON(TEXT("/Game/InfinityBladeWeapons/Weapons/Blade/Swords/Blade_BlackKnight/SK_Blade_BlackKnight.SK_Blade_BlackKnight"));
if (SK_WEAPON.Succeeded())
{
Weapon->SetSkeletalMesh(SK_WEAPON.Object);
}
Weapon->SetCollisionProfileName(TEXT("NoCollision"));
}
다음으로는 검을 캐릭터에 붙여줍시다.
ABCharacter.cpp
void AABCharacter::BeginPlay()
{
Super::BeginPlay();
FName WeaponSocket(TEXT("index_o1_r "));
auto CurWeapon = GetWorld()->SpawnActor<AABWeapon>(FVector::ZeroVector, FRotator::ZeroRotator);
if (nullptr != CurWeapon)
{
CurWeapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, WeaponSocket);
}
}
이제 무기를 바꿔줄 상자를 만들어 봅시다!
책에서는 맵 에셋에 있는 박스를 사용한다고 했지만 저는
언리얼 5에있는 일반상자를 사용하겠습니다.
다시 새 엑터생성
ABItemBox.h
public:
UPROPERTY(VisibleAnywhere, Category = Box)
UBoxComponent* Trigger;
UPROPERTY(VisibleAnywhere, Category = Box)
UStaticMeshComponent* Box;
ABItemBox.cpp
AABItemBox::AABItemBox()
{
// Set this actor to call Tick() every frame. You can turn this off to improve performance if you don't need it.
PrimaryActorTick.bCanEverTick = false;
Trigger = CreateDefaultSubobject<UBoxComponent>(TEXT("TRIGGER"));
Box = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BOX"));
RootComponent = Trigger;
Box->SetupAttachment(RootComponent);
Trigger->SetBoxExtent(FVector(40.0f, 42.0f, 30.0f));
static ConstructorHelpers::FObjectFinder<UStaticMesh> SM_BOX(TEXT("StaticMesh'/Game/LevelPrototyping/Meshes/SM_ChamferCube.SM_ChamferCube'"));
if (SM_BOX.Succeeded())
{
Box->SetStaticMesh(SM_BOX.Object);
}
Box->SetRelativeLocation(FVector(0.0f, -3.5f, -30.0f));
}
그리고 캐릭터와의 충돌을 위한 박스전용 채널을 만들어줍시다.
그리고 새 프로파일도 만들어줍시다.
캐릭터도 바꾸어 줍시다.
아래 코드를 추가해주고
ABItemBox.h
protected:
// Called when the game starts or when spawned
virtual void BeginPlay() override;
virtual void PostInitializeComponents() override;
private:
UFUNCTION()
void OnCharacterOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
ABItemBox.cpp
Trigger->SetCollisionProfileName(TEXT("ItemBox"));
Box->SetCollisionProfileName(TEXT("NoCollision"));
//~~~~
void AABItemBox::PostInitializeComponents()
{
Super::PostInitializeComponents();
Trigger->OnComponentBeginOverlap.AddDynamic(this, &AABItemBox::OnCharacterOverlap);
}
void AABItemBox::OnCharacterOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
ABLOG_S(Warning);
}
박스를 맵에 설치한후 플레이하면
위 처럼 경고 로그가 뜨게됩니다
이제 상자와 겹치면? 무기가 교체되도록 만들겠습니다.
ABItemBox.h
UPROPERTY(EditInstanceOnly, Category = Box)
TSubclassOf<class AABWeapon> WeaponItemClass;
ABItemBox.cpp
WeaponItemClass = AABWeapon::StaticClass();//클래스 기본값 설정
ABCharacter.h
bool CanSetWeapon();
void SetWeapon(class AABWeapon* NewWeapon);
UPROPERTY(VisibleAnywhere, category = Weapon)
class AABWeapon* CurrentWeapon;
ABCharacter.cpp
bool AABCharacter::CanSetWeapon() {
return (nullptr == CurrentWeapon);
}
void AABCharacter::SetWeapon(AABWeapon* NewWeapon) {
ABCHECK(nullptr != NewWeapon && nullptr == CurrentWeapon);
FName WeaponSocket(TEXT("index_01_r"));
if (nullptr != NewWeapon) {
NewWeapon->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, WeaponSocket);
NewWeapon->SetOwner(this);
CurrentWeapon = NewWeapon;
}
}
ABItemBox.cpp
void AABItemBox::OnCharacterOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
ABLOG_S(Warning);
auto ABCharacter = Cast<AABCharacter>(OtherActor);
ABCHECK(nullptr != ABCharacter);
if (nullptr != ABCharacter && nullptr != WeaponItemClass)
{
if (ABCharacter->CanSetWeapon())
{
auto NewWeapon = GetWorld()->SpawnActor<AABWeapon>(WeaponItemClass, FVector::ZeroVector, FRotator::ZeroRotator);
ABCharacter->SetWeapon(NewWeapon);
}
else
{
ABLOG(Warning, TEXT("%s can't equip weapon currently."), *ABCharacter->GetName());
}
}
}
여기까지 한다면 박스에 두번이상 오버랩 될 시 위와 같은 문구가 뜨게됩니다!
ABItemBox.h
private:
UFUCNTION()
void OnEffectFinished(class UParticleSystemComponent* PSystem);
public:
UPROPERTY(VisibleAnywhere, Category = Effect)
UParticleSystemComponent* Effect;
ABItemBox.cpp
AABItemBox::AABItemBox()
{
Effect = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("EFFECT")); // 이펙트
Effect->SetupAttachment(RootComponent);
static ConstructorHelpers::FObjectFinder<UParticleSystem> P_CHESTOPEN(TEXT("/Game/InfinityBladeGrassLands/Effects/FX_Treasure/Chest/P_TreasureChest_Open_Mesh.P_TreasureChest_Open_Mesh"));
if (P_CHESTOPEN.Succeeded())
{
Effect->SetTemplate(P_CHESTOPEN.Object);
Effect->bAutoActivate = false;
}
//~~~~
void AABItemBox::OnCharacterOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor, UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
ABLOG_S(Warning);
auto ABCharacter = Cast<AABCharacter>(OtherActor);
ABCHECK(nullptr != ABCharacter);
if (nullptr != ABCharacter && nullptr != WeaponItemClass)
{
if (ABCharacter->CanSetWeapon())
{
auto NewWeapon = GetWorld()->SpawnActor<AABWeapon>(WeaponItemClass, FVector::ZeroVector, FRotator::ZeroRotator);
ABCharacter->SetWeapon(NewWeapon);
Effect->Activate(true);
Box->SetHiddenInGame(true, true);
SetActorEnableCollision(false);
Effect->OnSystemFinished.AddDynamic(this, &AABItemBox::OnEffectFinished);
}
else
{
ABLOG(Warning, TEXT("%s can't equip weapon currently."), *ABCharacter->GetName());
}
}
}
void AABItemBox::OnEffectFinished(UParticleSystemComponent* PSystem) {
Destroy
}
여기 까지하면
보물 상자 오픈까지 되네요!
그리고 이제 웨폰 블루프린트를 몇개 만들고
상자마다 웨폰을 설정해주면
이제상자를 열어서 웨폰을 바꿀수 있습니다!
끝!
틀린점이 있다면 댓 달아주세요!
'언리얼 최고 > 언리얼 c++' 카테고리의 다른 글
이득우의 언리얼 C++ 정리 - 9 (충돌 설정과 대미지 전달) (0) | 2022.08.31 |
---|---|
이득우의 언리얼 C++ 정리 - 8 (애니메이션 시스템 활용) (1) | 2022.08.30 |
이득우의 언리얼 C++ 정리 - 7 (애니메이션 시스템의 설계) (0) | 2022.08.20 |
이득우의 언리얼 C++ 정리 - 6 (캐릭터의 제작과 컨트롤) (0) | 2022.08.20 |
이득우의 언리얼 C++ 정리 - 5 (폰의 제작과 조작) (0) | 2022.08.19 |
댓글