아이템 스폰, 획득, 파괴 복제하기
25강. 아이템 스폰, 획득, 파괴 복제하기
1. 이번 강의에서 해결할 문제
두 클라이언트가 같은 회복 아이템에 동시에 닿아 둘 다 회복하거나, 클라이언트가 로컬 Destroy해 자기 화면에서만 사라집니다. 아이템 생성·획득 판정·효과와 파괴는 하나의 서버 트랜잭션처럼 처리해야 합니다.
2. 학습 목표
3. 핵심 개념
아이템 Actor는 서버가 Spawn하고 bReplicates로 존재를 전달합니다. Overlap 콜백은 여러 복사본에서 발생할 수 있으므로 실제 획득 로직은 HasAuthority()에서만 실행합니다. 먼저 소비 상태를 잠그고 대상·거리·효과 가능 여부를 확인한 뒤 서버 HealthComponent를 변경하고 Actor를 Destroy합니다.
아이템이 사라진다는 현재 상태는 서버 Destroy가 전파합니다. 짧은 획득 파티클은 서버 승인 뒤 Multicast할 수 있지만 파티클이 유실돼도 회복과 아이템 제거는 유지돼야 합니다.
4. 단계별 실습
UCLASS()
class CAPTUREARENA_API ACaptureHealthPickup : public AActor
{
GENERATED_BODY()
public:
ACaptureHealthPickup();
protected:
virtual void NotifyActorBeginOverlap(AActor* OtherActor) override;
UFUNCTION(NetMulticast, Unreliable)
void Multicast_PlayConsumedFx(FVector_NetQuantize Location);
UPROPERTY(VisibleAnywhere)
TObjectPtr<USphereComponent> Trigger;
UPROPERTY(EditDefaultsOnly, Category = "Pickup",
meta = (ClampMin = "1.0"))
float HealAmount = 30.0f;
private:
bool bConsumed = false; // 서버에서만 판정하는 일회성 잠금
};
ACaptureHealthPickup::ACaptureHealthPickup()
{
PrimaryActorTick.bCanEverTick = false;
bReplicates = true;
Trigger = CreateDefaultSubobject<USphereComponent>(TEXT("Trigger"));
SetRootComponent(Trigger);
Trigger->SetSphereRadius(90.0f);
}
void ACaptureHealthPickup::NotifyActorBeginOverlap(AActor* OtherActor)
{
Super::NotifyActorBeginOverlap(OtherActor);
if (!HasAuthority() || bConsumed || !IsValid(OtherActor)) return;
UCaptureHealthComponent* Health =
OtherActor->FindComponentByClass<UCaptureHealthComponent>();
if (!Health || !Health->CanReceiveHealing()) return;
bConsumed = true;
Trigger->SetCollisionEnabled(ECollisionEnabled::NoCollision);
Health->HealOnServer(HealAmount);
Multicast_PlayConsumedFx(GetActorLocation());
Destroy();
}
void ACaptureHealthPickup::Multicast_PlayConsumedFx_Implementation(
FVector_NetQuantize Location)
{
if (GetNetMode() != NM_DedicatedServer)
{
SpawnPickupFx(Location);
}
}
Spawner는 GameMode나 서버 권한 Spawner Actor에서 GetWorld()->SpawnActor를 호출합니다. Respawn Timer도 서버에만 둡니다. 클라이언트 요청 기반 Pickup이라면 서버가 Overlap 또는 거리로 다시 확인하고 Client Actor 포인터를 믿지 않습니다.
5. 코드가 동작하는 이유
서버의 첫 유효 Overlap이 bConsumed를 먼저 설정해 같은 프레임의 두 번째 콜백을 막습니다. 서버 Health를 변경하고 서버 Actor를 Destroy하므로 모든 클라이언트가 같은 체력과 아이템 존재 상태에 수렴합니다. Multicast 효과는 결과와 분리돼 유실돼도 중복 획득이 생기지 않습니다.
6. 자주 하는 실수와 해결법
7. 직접 실습
8. 이해 점검 질문 3개
9. 핵심 요약
아이템 스폰, 획득, 파괴 복제하기 미니 퀴즈
선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.
학습을 마쳤나요?
직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.