일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 프로젝트
- fruitspuzzle
- 당구 연습
- timelessadventure
- ai controller
- unrealengine
- 리플렉션 시스템
- C++
- 2022 kakao
- fabrik ik
- gameinstancesubsystem
- 프로그래머스
- issac3d
- 백준
- 구현
- pcce 기출문제
- unity
- Algorithm
- pccp 기출문제
- netmode
- c#
- Summer/Winter Coding
- 2018 kakao
- 2019 kakao
- Unreal Engine
- network model
- 로컬 네트워크 연결
- enetrole
- 최대값과 최솟값
- 코딩테스트
- Today
- Total
LeeTaes 공부노트
[UE Team Project/T.A.] 10. 무기 교체 (CombatComponent, UI) 본문
[UE Team Project/T.A.] 10. 무기 교체 (CombatComponent, UI)
리태s 2024. 10. 11. 13:53개요
이번 포스팅에서는 여러 종류의 무기를 교체하는 방식에 대해 정리해보도록 하겠습니다.
구현 아이디어 설명
포스팅에서 다루지는 않았지만 무기는 총 4종류(맨손, 검, 활, 횃불)가 존재하며, 프로젝트 기획에서 무기는 장비 창을 통해 교체하는 것이 아닌 위젯을 띄워 선택된 위젯을 바탕으로 교체되도록 만들기로 하였습니다.
생각해낸 아이디어는 무기 교체 버튼을 누름과 동시에 위젯을 화면에 띄우고 마지막으로 마우스 Hover 이벤트를 받았던 무기로 교체하는 것입니다.
즉, 주먹/검/활/불 칸을 버튼으로 제작하고, Hover 이벤트 발생 시 위젯에 마지막으로 들어온 버튼이 무슨 버튼인지 체크하며 이후 해당 값에 따라 실제 무기를 교체하는 방식으로 제작하게 되었습니다.
Combat Component 무기 교체 로직 구현
CombatComponent는 현재 들고 있는 무기의 상태를 저장하며, 상태가 변경되는 경우 상태에 해당하는 무기를 새로 스폰하는 로직을 만들어주었습니다.
즉, 위젯이 비활성화 되는 동시에 무기 교체 함수 (ChangeWeapon)을 호출하며, 현재 착용중인 무기를 삭제하고 새로운 무기를 스폰하는 방식입니다.
CombatComponent.cpp
// 휠 버튼 Released 이벤트 발생 시 호출되는 함수
void UTA_CombatComponent::MiddleClickEnd()
{
if (!OwnerPlayer) return;
if (CombatState == ECombatState::CS_Idle || CombatState == ECombatState::CS_Dash)
{
ATA_PlayerController* PC = Cast<ATA_PlayerController>(OwnerPlayer->GetController());
if (PC)
{
// 위젯 안보이도록 설정
PC->VisibleWeaponSelectWidget(false);
}
// 무기 교체 함수 호출
ChangeWeapon();
}
}
// 무기 교체 함수
void UTA_CombatComponent::ChangeWeapon()
{
// 임시 타입(위젯에서 설정된 타입)에 따라 현재 타입 변환
EquippedState = TempEquippedState;
// 기존 무기가 존재하는 경우
if (IsValid(EquippedWeapon))
{
// 해당 무기 삭제
EquippedWeapon->RemoveWeapon();
EquippedWeapon = nullptr;
}
// 무기 장착
EquipWeapon();
}
// 무기 착용 함수
void UTA_CombatComponent::EquipWeapon()
{
// 현재 타입에 따른 무기가 존재하는 경우
if (WeaponClassMap[EquippedState])
{
// 무기 스폰 & 장착
if (WeaponClassMap[TempEquippedState])
{
ATA_WeaponBase* NewWeapon = GetWorld()->SpawnActor<ATA_WeaponBase>(WeaponClassMap[TempEquippedState], OwnerPlayer->GetActorTransform());
if (NewWeapon)
{
NewWeapon->EquipWeapon(OwnerPlayer->GetMesh());
EquippedWeapon = NewWeapon;
}
}
}
}
ChangeWeapon 위젯
위젯의 디자인은 다음과 같으며 모든 버튼에 Hover 이벤트가 발생하는 경우 CombatComponent의 임시 무기 상태(TempEquipState)를 변경하도록 구현하였습니다.
또한, 간단한 애니메이션을 넣어 무기 교체 위젯이 열리는 순간 점차 커지는 애니메이션을 재생하였습니다.
https://apth1023.tistory.com/28
ChangeWeapon.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "UI/TA_CustomWidget.h"
#include "TA_ChangeWeapon.generated.h"
/**
*
*/
UCLASS()
class TIMELESSADVENTURE_API UTA_ChangeWeapon : public UTA_CustomWidget
{
GENERATED_BODY()
protected:
virtual void NativeConstruct() override;
public:
void OpenWidget();
private:
UFUNCTION()
void OnHoverFist();
UFUNCTION()
void OnHoverSword();
UFUNCTION()
void OnHoverBow();
UFUNCTION()
void OnHoverTorch();
UFUNCTION()
void OnHoverCancel();
private:
UPROPERTY(meta = (BindWidget))
TObjectPtr<class UOverlay> OL_Main;
UPROPERTY(meta = (BindWidget))
TObjectPtr<class UButton> BTN_Fist;
UPROPERTY(meta = (BindWidget))
TObjectPtr<class UButton> BTN_Sword;
UPROPERTY(meta = (BindWidget))
TObjectPtr<class UButton> BTN_Bow;
UPROPERTY(meta = (BindWidget))
TObjectPtr<class UButton> BTN_Torch;
UPROPERTY(meta = (BindWidget))
TObjectPtr<class UButton> BTN_Cancel;
UPROPERTY(meta = (BindWidgetAnim), Transient)
TObjectPtr<UWidgetAnimation> ChangeWidgetOpen;
};
ChangeWeapon.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "UI/TA_ChangeWeapon.h"
#include "Interface/CombatComponentInterface.h"
#include "Component/TA_CombatComponent.h"
#include "Components/Overlay.h"
#include "Components/CanvasPanelSlot.h"
#include "Blueprint/WidgetLayoutLibrary.h"
#include "Components/Button.h"
void UTA_ChangeWeapon::NativeConstruct()
{
Super::NativeConstruct();
BTN_Fist->OnHovered.AddDynamic(this, &UTA_ChangeWeapon::OnHoverFist);
BTN_Sword->OnHovered.AddDynamic(this, &UTA_ChangeWeapon::OnHoverSword);
BTN_Bow->OnHovered.AddDynamic(this, &UTA_ChangeWeapon::OnHoverBow);
BTN_Torch->OnHovered.AddDynamic(this, &UTA_ChangeWeapon::OnHoverTorch);
BTN_Cancel->OnHovered.AddDynamic(this, &UTA_ChangeWeapon::OnHoverCancel);
}
void UTA_ChangeWeapon::OpenWidget()
{
FVector2D MousePos = UWidgetLayoutLibrary::GetMousePositionOnViewport(GetWorld());
UCanvasPanelSlot* slot = UWidgetLayoutLibrary::SlotAsCanvasSlot(OL_Main);
if (slot)
{
slot->SetPosition(MousePos);
}
PlayAnimation(ChangeWidgetOpen);
}
void UTA_ChangeWeapon::OnHoverFist()
{
if (OwnerActor)
{
ICombatComponentInterface* CombatComponentInterface = Cast<ICombatComponentInterface>(OwnerActor);
if (CombatComponentInterface)
{
CombatComponentInterface->GetCombatComponent()->SetChangeWeaponState(EEquippedState::ES_Idle);
}
}
}
void UTA_ChangeWeapon::OnHoverSword()
{
if (OwnerActor)
{
ICombatComponentInterface* CombatComponentInterface = Cast<ICombatComponentInterface>(OwnerActor);
if (CombatComponentInterface)
{
CombatComponentInterface->GetCombatComponent()->SetChangeWeaponState(EEquippedState::ES_Sword);
}
}
}
void UTA_ChangeWeapon::OnHoverBow()
{
if (OwnerActor)
{
ICombatComponentInterface* CombatComponentInterface = Cast<ICombatComponentInterface>(OwnerActor);
if (CombatComponentInterface)
{
CombatComponentInterface->GetCombatComponent()->SetChangeWeaponState(EEquippedState::ES_Bow);
}
}
}
void UTA_ChangeWeapon::OnHoverTorch()
{
if (OwnerActor)
{
ICombatComponentInterface* CombatComponentInterface = Cast<ICombatComponentInterface>(OwnerActor);
if (CombatComponentInterface)
{
CombatComponentInterface->GetCombatComponent()->SetChangeWeaponState(EEquippedState::ES_Torch);
}
}
}
void UTA_ChangeWeapon::OnHoverCancel()
{
if (OwnerActor)
{
ICombatComponentInterface* CombatComponentInterface = Cast<ICombatComponentInterface>(OwnerActor);
if (CombatComponentInterface)
{
CombatComponentInterface->GetCombatComponent()->SetChangeWeaponState(EEquippedState::ES_Cancel);
}
}
}
SetChangeWeaponState는 매우 간단히 임시 상태만 수정하도록 구현하였습니다.
결과
'프로젝트 > TimelessAdventure' 카테고리의 다른 글
[UE Team Project/T.A.] 12. Teleport (0) | 2024.10.22 |
---|---|
[UE Team Project/T.A.] 11. Boss AI (0) | 2024.10.22 |
[UE Team Project/T.A.] 9. 아이템 및 인벤토리 - 3 (UI - Inventory) (0) | 2024.10.11 |
[UE Team Project/T.A.] 8. 아이템 및 인벤토리 - 2 (UI - Slot) (0) | 2024.10.10 |
[UE Team Project/T.A.] 7. 아이템 및 인벤토리 - 1 (Component) (0) | 2024.10.10 |