Unity/게임개발

Photon 동기화 과정 정리 – HP(체력바) UI 예시

한니닝 2025. 7. 3. 23:33

캐릭터에 체력바(HUD)를 붙여놓고 멀티플레이 환경에서 상대 체력이 실시간으로 변하는 걸 예시로 포톤에서 동기화 과정을 정리한다.

1. 기본 구조

Player 프리팹에는 다음과 같은 컴포넌트가 붙어있다:

  • PhotonView
  • PlayerStatus → 체력 관리
  • PlayerHUD → 체력 UI (Slider)

내 클라이언트에서도, 상대 클라이언트에서도 모든 캐릭터 오브젝트가 존재한다.
즉, 내 캐릭터, 상대 캐릭터 전부 다 PlayerStatus, PlayerHUD를 갖고 있음.
차이점은 PhotonView.IsMine 값이 다르다는 것.

 

2. 체력 변화 → RPC로 동기화

내 캐릭터가 데미지를 받았을 때:

[PunRPC]
public void TakeDamage(int damage)
{
    if (!photonView.IsMine) return;

    currentHp -= damage;

    // 상대방 클라에게 내 캐릭터의 현재 체력값 전송
    photonView.RPC("SyncHp", RpcTarget.Others, currentHp);
}

 

그러면 상대 클라에서의 SyncHp() RPC가 호출된다:

[PunRPC]
public void SyncHp(int syncedHP)
{
    currentHp = syncedHP;
}

 

3. 상대 오브젝트에 반영이 되는 이유

처음에 의문이 들었던 부분이 이거였다.

내 체력값을 RPC로 상대 클라에 보냈는데
상대 클라에서는 이걸 받아서 어떻게 "내 캐릭터" 상태를 바꾸는거지?

 

→  Photon 구조상 photonView.RPC()는 해당 ViewID를 가진 오브젝트의 컴포넌트에만 호출된다고한다.

즉, 상대 클라 안에도 "나"의 오브젝트가 하나 있고,
그 오브젝트의 PlayerStatus 컴포넌트의 SyncHp()가 실행된다.

그 오브젝트 안의 HUD는 자연스럽게 Update()에서 이 currentHp 값을 참조해서 체력바를 그려주는 구조.

 

4. HUD에서 체력 UI 갱신

void Update()
{
    if (playerStatus == null) return;

    UpdateHealthUI();
}

void UpdateHealthUI()
{
    float healthRatio = playerStatus.HealthRatio;
    hpSlider.value = healthRatio;

    // 체력에 따라 색상도 바꿔줌
}

playerStatus는 같은 오브젝트에 붙은 PlayerStatus를 참조하고 있기 때문에,
RPC로 동기화된 currentHp가 자동으로 반영된다.

 

5. 내 UI vs 상대 UI 구분

HUD는 모든 플레이어 오브젝트에 붙어 있다.
그래서 내 클라에는 내 HUD도 있고, 상대 HUD도 있다.
각 HUD는 그 오브젝트 안의 PlayerStatus를 보고 체력바를 업데이트하니까, 따로 분기처리 안 해도 된다.

 

추가로 내 HUD와 상대 HUD의 체력바 색상을 다르게 하고 싶으면 Start()에서 photonView.IsMine을 체크해서 색만 바꿔주면 된다.

 

6. 전체 동기화 흐름 요약

  1. 내 캐릭터가 데미지 받음
  2. TakeDamage() 호출 → 내 클라의 currentHp 감소
  3. RPC("SyncHp", RpcTarget.Others) → 상대 클라의 "나" 오브젝트에서 SyncHp() 호출
  4. 상대 클라의 "나" 오브젝트의 currentHp가 변경됨
  5. 그 오브젝트에 붙은 PlayerHUD가 currentHp 기준으로 슬라이더 갱신