Godot 실시간 동기화
Godot 실시간 동기화 — Godot SDK로 플레이어 상태를 실시간 동기화하는 방법
중급실시간15초읽기 약 3분업데이트 2026-04-14
Godot SDK로 플레이어 상태를 실시간 동기화하는 방법
이 튜토리얼에서 배울 내용
Godot SDK 설치
채널 구독 및 이벤트 처리
상태 전송/수신
플레이어 참가/퇴장 처리
Godot 실시간 동기화
Godot 엔진으로 멀티플레이 게임을 만들 때, ConnectBase 게임 서버를 사용하면 룸 기반 WebSocket 동기화를 표준 흐름으로 구현할 수 있습니다. Godot SDK는 GameClient 노드(autoload 싱글톤)와 signal 기반 이벤트 모델을 제공합니다.
완성된 기능
GameClientautoload 로 게임 서버 연결join_room으로 룸 입장send_action/state_updatedsignal 로 위치/액션 동기화- 플레이어 입장/퇴장 signal 처리
사전 준비
- Godot 4.0 이상
- ConnectBase 콘솔에서 앱을 만들고
cb_pk_Public Key 확인 - 룸은 JavaScript SDK 또는 REST API 로 사전 생성합니다(Godot SDK는 룸 생성 메서드를 노출하지 않음). 빠른 테스트는 콘솔의 게임 서버 → 룸 메뉴에서 직접 생성
1. SDK 설치하기
GitHub 저장소의 sdk/godot/addons/connect_base_game 폴더를 프로젝트의 addons/ 아래로 복사합니다.
bash
cd your-godot-project
mkdir -p addons
cp -r /path/to/connectbase/sdk/godot/addons/connect_base_game addons/Godot 에디터를 다시 열어 프로젝트 → 프로젝트 설정 → 플러그인 에서 connect_base_game 을 활성화합니다. 활성화하면 GameClient 이름의 autoload singleton 이 자동 등록됩니다.
2. 연결 & 룸 입장하기
게임이 시작되면 ConnectBase 게임 서버에 연결하고, 사전 생성된 룸에 입장합니다.
player_sync.gd:
gdscript
extends Node
@export var public_key: String = "cb_pk_..."
@export var app_id: String = "your-app-id"
@export var room_id: String = "room_xxx"
func _ready() -> void:
# GameClient autoload 의 signal 에 연결
GameClient.connected.connect(_on_connected)
GameClient.disconnected.connect(_on_disconnected)
GameClient.state_updated.connect(_on_state_updated)
GameClient.player_joined.connect(_on_player_joined)
GameClient.player_left.connect(_on_player_left)
GameClient.game_error.connect(_on_game_error)
# 옵션: app_id / public_key 를 GameClient 내부에 세팅 후 connect_to_server 호출
# (구현 세부는 sdk/godot/addons/connect_base_game/game_client.gd 참고)
var err = GameClient.connect_to_server(public_key)
if err != OK:
push_error("game server connect failed: %s" % err)
func _on_connected() -> void:
GameClient.join_room(room_id, {"nickname": "Player1"})3. 내 상태 전송하기
매 물리 프레임마다 입력 또는 위치를 send_input / send_action 으로 전송합니다.
gdscript
@export var is_local_player: bool = true
var _last_send_t: float = 0.0
const SEND_INTERVAL := 0.05 # 50ms — 20Hz
func _physics_process(delta: float) -> void:
if not is_local_player: return
if not GameClient.is_connected: return
_last_send_t += delta
if _last_send_t < SEND_INTERVAL: return
_last_send_t = 0.0
# 입력 전송 (서버가 시퀀스 번호를 매김 — 클라이언트 예측 / reconciliation 단위)
var seq := GameClient.send_input({
"pos": {"x": position.x, "y": position.y},
"vel": {"x": velocity.x, "y": velocity.y},
"animation": current_animation,
})
# 일회성 액션
if Input.is_action_just_pressed("attack"):
GameClient.send_action("attack", {"target_id": "player_2", "damage": 25})💡 매 프레임 전송은 트래픽이 많습니다. 위 예제처럼
SEND_INTERVAL로 throttle 하거나, 위치 변화가 있을 때만 전송하세요.
4. 다른 플레이어 상태 수신하기
state_updated signal 의 페이로드에서 본인을 제외한 플레이어 상태를 적용합니다.
gdscript
func _on_state_updated(state: Dictionary) -> void:
var players = state.get("players", [])
for p in players:
if p.get("player_id") == GameClient.client_id: continue
var other := get_player(p.get("player_id"))
if other == null: continue
# 부드러운 위치 이동 (lerp)
var target := Vector2(p.position.x, p.position.y)
other.position = other.position.lerp(target, 0.3)
other.play_animation(p.animation)
func _on_player_joined(player: Dictionary) -> void:
spawn_remote_player(player.player_id, player.get("nickname", ""))
func _on_player_left(player_id: String) -> void:
despawn_remote_player(player_id)
func _on_disconnected() -> void:
push_warning("disconnected — try reconnect")
func _on_game_error(err: Dictionary) -> void:
push_error("GAME_ERROR: %s %s" % [err.get("code", "?"), err.get("message", "")])5. 테스트하기
- Godot 에디터에서 F5 실행
- 에디터를 하나 더 열거나 빌드된 게임을 실행하여 2인 테스트
- 한쪽에서 캐릭터를 움직이면 다른 쪽에서
_on_state_updated로 위치가 들어오는지 확인
다음 단계
- 매치큐 — JS SDK
cb.game.enqueueMatch로 ticket 등록 후 서버 Lua 가 매칭, 결과room_id를 클라이언트로 push - Lua 스크립트 — 룸 내부 게임 로직(공격 검증, 데미지 계산)을 서버 측 Lua 로 작성 → 클라이언트는
send_action만 호출 send_custom_message— RPC 스타일 메시지 (채팅, 신호) 전송- OfflineMode — 네트워크 끊김 대비
addons/connect_base_game/offline_mode.gd활용
이 튜토리얼이 도움이 됐나요?