본문 바로가기
🌐 유니티 (Unity)

Day 48 - 멀티플레이 WebGL 게임 개발의 핵심 요소 (1부)

by shin0707 2024. 12. 9.
728x90

  • 주제

>>  실시간 데이터 동기화

>>  서버 통신 최적화


  • 공부내용

WebGL 환경에서 멀티플레이 기능을 추가하려면 네트워크 구조와 실시간 동기화가 핵심이다.

이번 글에서는 실시간 데이터 동기화서버 통신 최적화라는 두 가지 주제에 집중하여,

WebGL 멀티플레이 게임 개발의 기본기를 다루겠다.

 

1. 실시간 데이터 동기화

멀티플레이 게임의 가장 중요한 부분은 다수의 클라이언트 간 데이터 동기화이다. WebGL 환경에서는 WebSocket을 사용해 빠르고 안정적인 실시간 데이터 전송을 구현할 수 있다.

 

1-1. WebSocket 연결 설정

WebSocket은 클라이언트와 서버 간의 지속적인 연결을 제공한다. Unity에서는 System.Net.WebSockets 네임스페이스를 사용해 WebSocket을 설정할 수 있다.

using System;
using System.Net.WebSockets;
using System.Text;
using System.Threading;
using UnityEngine;

public class WebSocketManager : MonoBehaviour
{
    private ClientWebSocket socket;

    public async void Connect(string serverUrl)
    {
        socket = new ClientWebSocket();
        try
        {
            await socket.ConnectAsync(new Uri(serverUrl), CancellationToken.None);
            Debug.Log("WebSocket 연결 성공");
            ReceiveMessages(); // 메시지 수신 대기
        }
        catch (Exception ex)
        {
            Debug.LogError($"WebSocket 연결 실패: {ex.Message}");
        }
    }

    private async void ReceiveMessages()
    {
        var buffer = new byte[1024];
        while (socket.State == WebSocketState.Open)
        {
            var result = await socket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
            var message = Encoding.UTF8.GetString(buffer, 0, result.Count);
            Debug.Log($"서버 메시지: {message}");
        }
    }

    public async void SendMessage(string message)
    {
        if (socket.State == WebSocketState.Open)
        {
            var encodedMessage = Encoding.UTF8.GetBytes(message);
            var buffer = new ArraySegment<byte>(encodedMessage);
            await socket.SendAsync(buffer, WebSocketMessageType.Text, true, CancellationToken.None);
        }
    }

    private async void OnApplicationQuit()
    {
        if (socket != null && socket.State == WebSocketState.Open)
        {
            await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "클라이언트 종료", CancellationToken.None);
        }
    }
}

 

설명:

  • Connect: 서버와 연결을 시작한다.
  • ReceiveMessages: 서버에서 전송된 메시지를 비동기적으로 수신한다.
  • SendMessage: 클라이언트에서 서버로 데이터를 전송한다.
  • OnApplicationQuit: 클라이언트 종료 시 WebSocket 연결을 닫는다.

 

 

1-2. 실시간 데이터 전송의 효율성

모든 데이터를 매번 전송하면 네트워크 대역폭이 낭비된다. 변경된 데이터만 전송하거나 적절한 주기로 데이터를 전송하는 것이 중요하다.

IEnumerator SendPosition(Vector3 position)
{
    while (true)
    {
        string json = JsonUtility.ToJson(new { x = position.x, y = position.y, z = position.z });
        SendMessage(json);
        yield return new WaitForSeconds(0.1f); // 100ms 간격
    }
}

 

위 코드는 플레이어 위치 데이터를 100ms 간격으로 서버에 전송한다.

이렇게 하면 데이터 전송량을 줄이고 서버 부하를 낮출 수 있다.


2. 서버 통신 최적화

멀티플레이 환경에서는 서버와의 통신이 게임 성능에 큰 영향을 미친다.

최적화된 통신 설계를 통해 게임 속도를 유지하면서도 정확한 데이터를 동기화할 수 있다.

 

2-1. 주기적인 데이터 송수신

 

  • 데이터 전송 주기를 설정해 과도한 트래픽을 방지한다.
  • 예를 들어, 플레이어 위치 변화가 적을 경우 데이터 전송을 건너뛴다.
Vector3 previousPosition;

void Update()
{
    if (Vector3.Distance(transform.position, previousPosition) > 0.1f) // 0.1 이상 이동 시 전송
    {
        StartCoroutine(SendPosition(transform.position));
        previousPosition = transform.position;
    }
}

 

 

 

2-2. 네트워크 프로토콜 설계

멀티플레이 게임에서 중요한 데이터와 덜 중요한 데이터를 구분해 전송한다.

  • 중요 데이터: 플레이어 위치, 점수 등.
  • 덜 중요한 데이터: 애니메이션 상태, 채팅 메시지 등.

 

중요 데이터 전송 구조:

json

{
    "type": "position",
    "playerId": "12345",
    "position": { "x": 1.2, "y": 0.5, "z": 0.0 }
}

 

 

덜 중요한 데이터 전송 구조:

json

{
    "type": "chat",
    "playerId": "12345",
    "message": "안녕하세요!"
}

 


 

<Day49 예고>

 

다음 글에서는 플레이어 간 상호작용을 구현하는 방법에 대해 알아보겠다.

  • 플레이어 위치 갱신
  • 충돌 처리
  • 채팅 시스템 구현

WebGL 환경에서 상호작용을 최적화하는 방법을 함께 살펴보자! 🎮

728x90

loading