๐
2025-12-01
์ค๋๊ฐ ์๋ ์ ์๋ ์กํฐ์ ํ๋ ์ด์ด ๊ฐ์ ๋คํธ์ํฌ ํต์ ์ ๊ตฌํํ ๋, ํ๋ ์ด์ด ์ปจํธ๋กค๋ฌ๋ฅผ ์ค์ฌ์(Mediator) ํจํด์ผ๋ก ํ์ฉํ๋ค.
์ ์๋(ATSCraftingTable)๋ ์๋์ ๋ฐฐ์น๋ ์กํฐ๋ก, ํน์ ํ๋ ์ด์ด์ ์์ ๊ฐ ์๋๋ค. ์ธ๋ฆฌ์ผ์ RPC๋ ๊ธฐ๋ณธ์ ์ผ๋ก Owner๋ฅผ ํตํด ๋ผ์ฐํ
๋๊ธฐ ๋๋ฌธ์, ์ค๋๊ฐ ์๋ ์กํฐ์์ ์ง์ ํด๋ผ์ด์ธํธ RPC๋ฅผ ํธ์ถํ๋ฉด ์ด๋ ํด๋ผ์ด์ธํธ๋ก ๋ณด๋ด์ผ ํ ์ง ์ ์ ์๋ค.
ํด๋ผ์ด์ธํธ โ ํ๋ ์ด์ด ์ปจํธ๋กค๋ฌ โ ์ ์๋
// PlayerController.h
UFUNCTION(Server, Reliable, WithValidation, BlueprintCallable, Category = "Crafting")
void ServerRequestCraft(ATSCraftingTable* CraftingTable, int32 RecipeID);
// PlayerController.cpp
void ATSPlayerController::ServerRequestCraft_Implementation(
ATSCraftingTable* CraftingTable, int32 RecipeID)
{
if (!CraftingTable) return;
ATSCharacter* TSCharacter = Cast<ATSCharacter>(GetPawn());
if (!TSCharacter) return;
// ์ ์๋์ ํจ์๋ฅผ ๋์ ํธ์ถ
CraftingTable->ServerRequestCraft(RecipeID, TSCharacter);
}
ํด๋ผ์ด์ธํธ UI์์ ์ ์ ๋ฒํผ์ ๋๋ฅด๋ฉด โ ํ๋ ์ด์ด ์ปจํธ๋กค๋ฌ์ ServerRequestCraft RPC ํธ์ถ โ ์๋ฒ์์ ์ ์๋์ ์ค์ ์ ์ ๋ก์ง ์คํ
์ ์๋ โ ํ๋ ์ด์ด ์ปจํธ๋กค๋ฌ โ ํด๋ผ์ด์ธํธ
// CraftingTable.cpp - ์ ์ ์๋ฃ ํ
void ATSCraftingTable::StartCrafting(int32 RecipeID, ATSCharacter* InstigatorCharacter)
{
// ... ์ ์ ๋ก์ง ...
ATSPlayerController* PC = Cast<ATSPlayerController>(InstigatorCharacter->GetController());
if (!PC) return;
int32 SlotIndex = CraftingInventory->PlaceCraftResult(PC, RecipeData.ResultItemID, RemainingQuantity);
// ํ๋ ์ด์ด ์ปจํธ๋กค๋ฌ๋ฅผ ํตํด ํด๋ผ์ด์ธํธ์ ์๋ฆผ
PC->ClientNotifyCraftResult(SlotIndex);
}
// PlayerController.cpp
void ATSPlayerController::ClientNotifyCraftResult_Implementation(int32 SlotIndex)
{
// ๋ธ๋ฆฌ๊ฒ์ดํธ ๋ธ๋ก๋์บ์คํธ๋ก UI ์
๋ฐ์ดํธ
OnCraftComplete.Broadcast(SlotIndex);
}
์ ์ ์๋ฃ โ ํ๋ ์ด์ด ์ปจํธ๋กค๋ฌ์ ClientNotifyCraftResult RPC๋ก ๊ฒฐ๊ณผ ์ ๋ฌ โ OnCraftComplete ๋ธ๋ฆฌ๊ฒ์ดํธ ๋ธ๋ก๋์บ์คํธ โ UI๊ฐ ์ฌ๋กฏ ์
๋ฐ์ดํธ
1. ๋คํธ์ํฌ ๋ผ์ฐํ ๋ฌธ์ ํด๊ฒฐ
2. ๊ถํ ๊ฒ์ฆ ์ค์ํ
bool ATSPlayerController::ServerRequestCraft_Validate(
ATSCraftingTable* CraftingTable, int32 RecipeID)
{
return CraftingTable && RecipeID > 0;
}
ํ๋ ์ด์ด ์ปจํธ๋กค๋ฌ์์ ํ ๋ฒ๋ง ๊ฒ์ฆํ๋ฉด ๋จ
3. UI ํต์ ๊ฐ์ํ
// PlayerController.h
UFUNCTION(Server, Reliable, BlueprintCallable, Category = "Crafting")
void ServerNotifyCraftingTableClosed(UTSCraftingTableInventory* CraftingInventory);
// PlayerController.cpp
void ATSPlayerController::ServerNotifyCraftingTableClosed_Implementation(
UTSCraftingTableInventory* CraftingInventory)
{
if (CraftingInventory)
{
CraftingInventory->OnPlayerClosedUI(this);
}
}
ํด๋ผ์ด์ธํธ๊ฐ ์ ์๋ UI๋ฅผ ๋ซ์ผ๋ฉด โ ์๋ฒ์ ์๋ฆผ โ ์ ์๋ ์ธ๋ฒคํ ๋ฆฌ ์ ๋ฆฌ. ์ด๊ฒ๋ ํ๋ ์ด์ด ์ปจํธ๋กค๋ฌ๋ฅผ ํตํด ์ฒ๋ฆฌ.
์ฒ์์ "์ ์๋์์ ์ง์ RPC ๋ ๋ฆฌ๋ฉด ๋์ง ์๋?"๋ผ๊ณ ์๊ฐํ๋๋ฐ, Owner๊ฐ ์๋ ์กํฐ๋ ์ด๋ ํด๋ผ์ด์ธํธํํ ๋ณด๋ผ์ง ๋ชฐ๋ผ์ ์ ๋๋ค๋ ๊ฑธ ๊นจ๋ฌ์๋ค. ํ๋ ์ด์ด ์ปจํธ๋กค๋ฌ๊ฐ ์ค๊ฐ์์ ์ ๋ฌํ๋ ์ค์ฌ์ ์ญํ ์ ํ๋๊น ๊น๋ํ๊ฒ ํด๊ฒฐ๋๋ค.
์ด ํจํด์ ํต์ฌ์ "ํต์ ๊ฒฝ๋ก๋ฅผ ๋ช ํํ๊ฒ ๋ง๋๋ ๊ฒ"์ธ ๊ฒ ๊ฐ๋ค. UI โ PlayerController โ CraftingTable โ PlayerController โ UI ์ด๋ฐ ์์ผ๋ก ํญ์ ํ๋ ์ด์ด ์ปจํธ๋กค๋ฌ๋ฅผ ๊ฑฐ์น๋๊น ๋๊ฐ ๋๊ตฌํํ ๋งํ๋์ง ํท๊ฐ๋ฆด ์ผ์ด ์๋ค.
๊ทผ๋ฐ ์ด๋ ๊ฒ ํ๋ฉด ํ๋ ์ด์ด ์ปจํธ๋กค๋ฌ๊ฐ ๋๋ฌด ๋ง์ ๊ฑธ ์๊ฒ ๋๋ ๊ฑด ์๋๊ฐ ์ถ๊ธฐ๋ ํ๋ค. ์ ์๋๋ ์๊ณ , ์ธ๋ฒคํ ๋ฆฌ๋ ์๊ณ , UI๋ ์๊ณ ... ๋์ค์ ์์คํ ์ด ๋ ๋ณต์กํด์ง๋ฉด ํ๋ ์ด์ด ์ปจํธ๋กค๋ฌ๊ฐ God Object๊ฐ ๋ ์๋ ์์ ๊ฒ ๊ฐ์๋ฐ, ๊ทธ๋ ๊ฐ์ ๋ฆฌํฉํ ๋ง ๊ณ ๋ฏผํด๋ด์ผ๊ฒ ๋ค.