TIL: Unreal Engine C++ OnRep 함수와 Blueprint RepNotify 사용 기준 이해하기
오늘 배운 내용
오늘은 Unreal Engine 멀티플레이에서 C++ OnRep_함수와 Blueprint RepNotify 함수를 언제 사용하면 좋은지 정리했다.
둘 다 서버에서 변경된 replicated 변수 값을 클라이언트가 받았을 때 특정 함수를 실행할 수 있게 해주는 기능이다.
하지만 실제로 사용할 때는 성격이 조금 다르다.
핵심은 다음과 같다.
게임 규칙에 영향을 주는 중요한 상태값
→ C++ OnRep 함수
UI, 애니메이션, 이펙트처럼 화면 표현 중심의 값
→ Blueprint RepNotify 함수
한 번만 발생하는 알림이나 이벤트
→ RPC
즉, 무조건 RepNotify를 쓰는 것이 아니라 이 값이 계속 유지되어야 하는 상태인지, 아니면 한 번만 발생하는 이벤트인지 먼저 구분해야 한다.
1. C++ OnRep 함수의 의미
C++에서 OnRep_함수는 replicated 변수가 서버에서 변경되고, 그 값이 클라이언트로 복제되었을 때 자동으로 호출되는 함수다.
예를 들어 HP 값을 복제하고 싶다면 다음처럼 작성할 수 있다.
UPROPERTY(ReplicatedUsing = OnRep_HP)
float HP;
UFUNCTION()
void OnRep_HP();
그리고 OnRep_HP() 함수 안에서 HP가 변경되었을 때 실행할 처리를 작성한다.
void AMyCharacter::OnRep_HP()
{
UpdateHPBar();
PlayHitEffect();
}
흐름으로 보면 다음과 같다.
서버에서 HP 변경
↓
HP 값이 클라이언트로 복제됨
↓
클라이언트에서 OnRep_HP() 자동 호출
↓
HP UI 갱신 또는 피격 이펙트 실행
즉, C++ OnRep 함수는 서버에서 바뀐 상태를 클라이언트가 받았을 때 그 상태에 맞는 후처리를 실행하는 용도로 사용한다.
2. C++ OnRep 함수의 중요한 특징
C++ OnRep 함수는 기본적으로 클라이언트에서 자동 호출된다.
서버에서 값을 변경했다고 해서 서버에서도 OnRep 함수가 자동으로 호출되는 것은 아니다.
예를 들어 서버에서 데미지를 받아 HP를 줄였다고 하면,
void AMyCharacter::ApplyDamage(float Damage)
{
if (HasAuthority())
{
HP -= Damage;
}
}
이 경우 HP 값은 클라이언트로 복제되고, 클라이언트에서는 OnRep_HP()가 자동 호출된다.
하지만 서버에서도 같은 처리가 필요하다면 직접 호출해야 한다.
void AMyCharacter::ApplyDamage(float Damage)
{
if (HasAuthority())
{
HP -= Damage;
// 서버에서도 HP 변경 처리가 필요하다면 직접 호출
OnRep_HP();
}
}
정리하면 다음과 같다.
서버
HP 변경
↓
필요하면 OnRep_HP() 직접 호출
클라이언트
HP 값 복제 받음
↓
OnRep_HP() 자동 호출
이 부분이 C++ OnRep을 사용할 때 중요한 포인트다.
3. C++ OnRep을 쓰면 좋은 상황
C++ OnRep 함수는 게임의 핵심 로직과 연결된 상태값에 사용하기 좋다.
예를 들면 다음과 같다.
HP
MP
사망 여부
무기 장착 상태
탄약 수
팀 정보
점수
게임 진행 상태
캐릭터 상태
이런 값들은 단순히 화면에 보여주기만 하는 값이 아니라 게임 규칙과 직접 연결된다.
예를 들어 HP가 0이 되면 캐릭터가 죽어야 하고, 무기가 바뀌면 공격 방식이나 애니메이션도 바뀔 수 있다.
따라서 이런 중요한 상태는 Blueprint보다 C++에서 명확하게 관리하는 것이 좋다.
4. HP 변경 예시
HP는 대표적으로 C++ OnRep을 쓰기 좋은 값이다.
UPROPERTY(ReplicatedUsing = OnRep_HP)
float HP;
UFUNCTION()
void OnRep_HP();
void AMyCharacter::OnRep_HP()
{
UpdateHPBar();
if (HP <= 0)
{
PlayDeathAnimation();
}
}
흐름은 다음과 같다.
서버에서 데미지 계산
↓
HP 값 변경
↓
변경된 HP가 클라이언트로 복제됨
↓
클라이언트에서 OnRep_HP() 실행
↓
HP바 갱신
↓
HP가 0 이하라면 사망 애니메이션 실행
HP는 현재 값이 계속 유지되어야 하는 상태다.
그래서 이런 값은 RepNotify 방식이 잘 맞는다.
5. 무기 장착 상태 예시
무기 장착 상태도 C++ OnRep을 쓰기 좋은 예시다.
UPROPERTY(ReplicatedUsing = OnRep_CurrentWeapon)
AWeapon* CurrentWeapon;
UFUNCTION()
void OnRep_CurrentWeapon();
void AMyCharacter::OnRep_CurrentWeapon()
{
AttachWeaponMesh();
UpdateWeaponUI();
}
서버에서 현재 무기를 변경하면, 클라이언트는 복제된 CurrentWeapon 값을 받고 OnRep_CurrentWeapon()을 실행한다.
서버에서 CurrentWeapon 변경
↓
CurrentWeapon 값이 클라이언트로 복제됨
↓
클라이언트에서 OnRep_CurrentWeapon() 호출
↓
무기 메시 부착
↓
무기 UI 갱신
무기 장착은 단순한 화면 표시가 아니라 공격 가능 여부, 애니메이션, 충돌, 소켓 부착 등과 연결될 수 있다.
그래서 이런 기능은 C++ OnRep으로 관리하는 것이 더 안정적이다.
6. Blueprint RepNotify 함수의 의미
Blueprint에서도 변수를 RepNotify로 설정할 수 있다.
Blueprint 변수에서 Replication 설정을 RepNotify로 바꾸면, 해당 변수 값이 변경되었을 때 자동으로 Notify 함수가 만들어진다.
예를 들어 bIsDoorOpen이라는 변수를 RepNotify로 만들면 다음처럼 사용할 수 있다.
bIsDoorOpen 값 변경
↓
RepNotify 함수 실행
↓
문 열림 또는 닫힘 애니메이션 실행
Blueprint RepNotify는 C++보다 빠르게 구현할 수 있고, 시각적인 처리에 편하다.
특히 UI, 애니메이션, 사운드, 이펙트처럼 게임 규칙보다 표현에 가까운 기능에 잘 맞는다.
7. Blueprint RepNotify를 쓰면 좋은 상황
Blueprint RepNotify는 화면 표현이나 간단한 반응 처리에 사용하기 좋다.
예를 들면 다음과 같다.
문 열림 / 닫힘 애니메이션
불 켜짐 / 꺼짐
캐릭터 머리 위 이름표 표시
Ready 아이콘 표시
닉네임 색상 변경
간단한 사운드 출력
간단한 이펙트 재생
이런 기능들은 게임의 핵심 규칙보다는 플레이어에게 보여주는 표현에 가깝다.
그래서 Blueprint에서 빠르게 처리해도 충분한 경우가 많다.
8. 문 열림 상태 예시
문이 열렸는지 닫혔는지를 나타내는 bIsDoorOpen 변수가 있다고 하면, Blueprint에서 RepNotify로 설정할 수 있다.
bIsDoorOpen = true
↓
RepNotify 실행
↓
문 열림 애니메이션 재생
반대로 값이 false가 되면 문 닫힘 애니메이션을 재생할 수 있다.
bIsDoorOpen = false
↓
RepNotify 실행
↓
문 닫힘 애니메이션 재생
이런 경우는 C++로 복잡하게 처리하지 않아도 Blueprint RepNotify로 충분히 구현할 수 있다.
다만 문이 실제로 길을 막는 충돌 상태까지 바뀐다면 서버에서 상태를 관리하고 복제해야 한다.
즉, 문 애니메이션은 Blueprint에서 처리할 수 있지만, 문이 열렸는지 닫혔는지에 대한 최종 판단은 서버 기준으로 처리하는 것이 좋다.
9. 플레이어 Ready 표시 예시
멀티플레이 대기방에서 플레이어가 준비 완료 상태가 되었을 때도 Blueprint RepNotify를 사용할 수 있다.
예를 들어 bIsReady 변수를 RepNotify로 설정한다.
서버에서 bIsReady 변경
↓
클라이언트로 bIsReady 복제
↓
RepNotify 실행
↓
Ready 아이콘 표시
↓
닉네임 색상 변경
이 기능은 게임 규칙 자체보다는 UI 표시와 관련이 크다.
그래서 Blueprint RepNotify로 처리하기 좋다.
10. C++ OnRep과 Blueprint RepNotify 차이
두 기능은 비슷해 보이지만 실제 사용 기준은 다르다.
C++ OnRep 함수
→ 핵심 게임 상태를 안정적으로 관리할 때 사용
Blueprint RepNotify 함수
→ UI, 애니메이션, 이펙트처럼 표현 중심 처리에 사용
표로 정리하면 다음과 같다.
구분C++ OnRep 함수Blueprint RepNotify 함수
| 주요 용도 | 핵심 게임 로직 | 화면 표현, UI, 애니메이션 |
| 호출 위치 | 주로 클라이언트에서 자동 호출 | 서버와 클라이언트 모두에서 호출될 수 있음 |
| 직접 호출 | 가능 | 일반적으로 직접 호출보다는 변수 변경에 반응 |
| 예시 | HP, 무기, 점수, 사망 상태 | 문 애니메이션, Ready 표시, 이펙트 |
| 장점 | 안정적이고 명확함 | 빠르게 구현 가능 |
| 추천 상황 | 나중에 확장될 중요한 시스템 | 간단한 시각 처리 |
즉, 나중에 시스템이 커질 가능성이 있는 중요한 기능은 C++ OnRep으로 만드는 것이 좋고, 빠르게 화면 표현을 처리하고 싶은 기능은 Blueprint RepNotify를 사용하면 된다.
11. RepNotify와 RPC의 차이
오늘 가장 중요한 기준은 RepNotify와 RPC의 차이다.
RepNotify는 상태값에 적합하다.
HP = 100
HP = 80
HP = 50
이런 값은 현재 값이 중요하다.
플레이어가 나중에 들어와도 현재 HP가 얼마인지 알아야 한다.
그래서 이런 값은 RepNotify로 관리하는 것이 좋다.
반면 RPC는 한 번 발생하는 이벤트에 적합하다.
"Player2 has joined the game."
"공격 버튼을 눌렀다."
"채팅 메시지를 보냈다."
이런 것은 계속 유지되는 상태라기보다 특정 순간에 발생하는 이벤트다.
따라서 이런 경우는 RepNotify보다 RPC가 더 자연스럽다.
정리하면 다음과 같다.
계속 유지되어야 하는 값
→ RepNotify
한 번만 발생하는 행동이나 알림
→ RPC
12. 접속 알림 기능에 적용하기
현재 만들고 있는 접속 알림 기능은 RepNotify보다 RPC가 더 적합하다.
예를 들어 클라이언트2가 접속했을 때 클라이언트1 화면에 다음 메시지를 띄우고 싶다고 하면,
"Player2 has joined the game."
이 메시지는 계속 유지되어야 하는 상태가 아니다.
한 번 출력되면 되는 이벤트다.
따라서 접속 알림은 다음과 같은 흐름이 적합하다.
클라이언트 접속
↓
서버 GameMode::PostLogin()에서 접속 감지
↓
GameState 또는 PlayerController를 통해 클라이언트들에게 RPC 전달
↓
각 클라이언트 UI에 접속 메시지 출력
즉, 접속 알림은 상태 동기화가 목적이 아니라 순간 이벤트 전달이 목적이다.
그래서 RepNotify보다 RPC 구조가 더 알맞다.
13. 상태와 이벤트 구분하기
멀티플레이 기능을 만들 때 가장 먼저 구분해야 할 것은 상태인지 이벤트인지다.
상태는 계속 유지되는 값이다.
HP
점수
팀
현재 무기
사망 여부
준비 완료 여부
이런 값은 현재 상태가 중요하기 때문에 RepNotify가 잘 맞는다.
반면 이벤트는 특정 순간에 한 번 발생하는 동작이다.
채팅 메시지 전송
접속 알림 출력
공격 요청
스킬 사용 요청
효과음 재생 요청
이런 것은 RPC가 잘 맞는다.
정리하면 다음과 같다.
상태(State)
→ RepNotify
이벤트(Event)
→ RPC
이 기준을 잡으면 네트워크 구조를 훨씬 깔끔하게 설계할 수 있다.
14. 실제 게임 제작 시 판단 기준
실제 게임을 만들 때는 다음 기준으로 선택하면 된다.
게임 규칙에 영향을 주는 값인가?
→ C++ OnRep
화면에 보여주는 표현인가?
→ Blueprint RepNotify
한 번만 발생하는 알림이나 행동인가?
→ RPC
예를 들어 HP는 게임 규칙에 영향을 준다.
HP가 0이 되면 죽음
데미지 계산과 연결됨
UI와도 연결됨
그래서 C++ OnRep이 적합하다.
문 열림 애니메이션은 표현에 가깝다.
문이 열리는 모습을 보여줌
사운드나 애니메이션 재생
그래서 Blueprint RepNotify로 처리할 수 있다.
접속 알림은 한 번 발생하는 이벤트다.
플레이어가 들어온 순간 메시지를 출력
계속 유지될 필요 없음
그래서 RPC가 적합하다.
오늘 헷갈렸던 점
오늘 헷갈렸던 부분은 C++ OnRep과 Blueprint RepNotify가 둘 다 비슷해 보인다는 점이었다.
둘 다 값이 바뀌었을 때 함수를 실행한다는 점에서는 비슷하다.
하지만 실제로는 사용하는 목적이 다르다.
C++ OnRep은 HP, 무기, 점수처럼 게임 규칙과 연결되는 중요한 상태값에 적합하다.
반면 Blueprint RepNotify는 문 애니메이션, Ready 아이콘, 이펙트처럼 화면 표현을 빠르게 처리할 때 적합하다.
또 접속 알림처럼 “OOO has joined the game.”을 출력하는 기능은 RepNotify보다 RPC가 더 적합하다는 점도 중요했다.
처음에는 접속 알림도 RepNotify로 처리할 수 있을 것 같았지만, 접속 알림은 계속 유지되는 값이 아니라 한 번 발생하는 이벤트다.
따라서 상태와 이벤트를 먼저 구분하는 것이 중요하다.
오늘의 핵심 정리
- C++ OnRep 함수는 replicated 변수가 클라이언트로 복제되었을 때 호출되는 함수다.
- C++ OnRep은 보통 클라이언트에서 자동 호출된다.
- 서버에서도 같은 처리가 필요하면 OnRep 함수를 직접 호출해야 한다.
- HP, MP, 사망 여부, 무기 장착 상태처럼 중요한 게임 상태는 C++ OnRep이 적합하다.
- 무기 장착 상태는 공격, 애니메이션, 충돌, 소켓 부착과 연결될 수 있으므로 C++에서 관리하는 것이 좋다.
- Blueprint RepNotify는 Blueprint 변수 값이 변경되었을 때 Notify 함수를 실행하는 기능이다.
- Blueprint RepNotify는 UI, 애니메이션, 이펙트처럼 화면 표현 중심 기능에 적합하다.
- 문 열림 애니메이션, 불 켜짐, Ready 아이콘 표시 같은 기능은 Blueprint RepNotify로 처리할 수 있다.
- RepNotify는 계속 유지되어야 하는 상태값에 적합하다.
- RPC는 한 번만 발생하는 이벤트에 적합하다.
- HP, 점수, 팀, 현재 무기처럼 현재 값이 중요한 것은 RepNotify로 관리하는 것이 좋다.
- 접속 알림, 채팅 메시지, 공격 요청처럼 순간적으로 발생하는 것은 RPC가 더 적합하다.
- 접속 알림은 상태 동기화가 아니라 이벤트 전달이 목적이므로 RPC 구조가 자연스럽다.
- 멀티플레이 기능을 만들 때는 먼저 상태인지 이벤트인지 구분해야 한다.
- 상태라면 RepNotify를 고려하고, 이벤트라면 RPC를 고려한다.
- 게임 규칙에 영향을 주는 값은 C++ OnRep으로 관리하는 것이 좋다.
- 화면 표현만 바꾸는 값은 Blueprint RepNotify로 빠르게 처리할 수 있다.
- 중요한 네트워크 구조일수록 C++에서 명확하게 관리하는 것이 좋다.
정리하면 C++ OnRep과 Blueprint RepNotify는 둘 다 값 변경에 반응하는 기능이지만, 사용하는 목적이 다르다.
C++ OnRep은 게임의 핵심 상태를 동기화하고 후처리할 때 적합하고, Blueprint RepNotify는 UI나 애니메이션처럼 화면 표현을 처리할 때 적합하다.
그리고 접속 알림이나 채팅처럼 한 번 발생하는 기능은 RepNotify보다 RPC를 사용하는 것이 더 자연스럽다.
'unreal 8기' 카테고리의 다른 글
| 2026-6-19 TIL (0) | 2026.06.19 |
|---|---|
| 2026-6-18 TIL (0) | 2026.06.19 |
| 2026-6-16 TIL (0) | 2026.06.16 |
| 2026-6-15 TIL (0) | 2026.06.15 |
| 2026-6-11 TIL (0) | 2026.06.11 |