이번에 게임 내부 시간 로직을 개선하려고합니다.

문의 응대 : 평일 오전 10시 ~ 오후 6시
문의를 남기실 경우 다음 항목을 작성해 주세요.
정보가 부족하거나 응대시간 외 문의하는 경우 확인 및 답변이 지연될 수 있습니다.

위와 같이 조언 해주신대로 현재 로직을 바꾸는 중입니다.

로직을 바꾸면서 한가지 의문점이 생겼는데 어떻게 해결해야 될지 감이 안와서 문의를 드립니다.

현재 게임에 핫타임이 존재합니다. 해당 기능은 정확한 시간에 발동이 되야하는데

기존 로직에서는 매 1분마다 시간을 가져와서 문제가 안되었지만 위와 같이 로직을 개선 할 경우

± 알파의 시간 오차가 생겨버려서 어떻게 해야 될지 고민입니다 ㅠㅠ

도움주시면 감사드립니다

안녕하세요 개발자님,
문의 해주신 내용 확인하여 안내드릴 수 있도록 하겠습니다.

항상 감사드립니다. 답변 기다리겠습니다 :)

안녕하세요 개발자님.

먼저 뒤끝 서버타임의 경우 5분에 한번씩 호출하는 주기를 추천하고 있습니다.

만약 게임의 시간 체크가 빈번하게 발생할 경우, 서버타임을 로컬에서 시간을 더하는 식으로 구현하여 사용하시는 것을 추천드립니다.

로직은 다음과 같습니다.

  1. 로그인 이후 서버타임 1회 호출
  2. 해당 서버타임을 FixedUpdate에서 업데이트하면서 실시간처럼 사용(백그라운드 및 동기에도 영향 받지 않음)
  3. 5분마다 서버에서 시간을 불러와 현재 시간과 맞춤(InvokeRepeating)

코드의 경우, cs 전체를 제공하였습니다. TimeManager.cs를 생성 후, TimeManager.Instance.currentTime을 이용하시면 되겠습니다.

// Copyright 2013-2022 AFI, Inc. All Rights Reserved.

using System;
using System.Threading;
using UnityEngine;
using BackEnd;
public class TimeManager : MonoBehaviour
{
    float oldTime;
    private DateTime utcTime;
    public DateTime currentTime;
    DateTime serverTime;

    bool isChangeServerTime = false;
    bool isServerTimeUpdate = false;

    int initTimeCount = 3;

    private static TimeManager instance = null;

    public static TimeManager Instance
    {
        get => instance;
    }

    void Awake()
    {
        if (instance == null)
        {
            instance = this;
        }
    }

    void Start()
    {
        Backend.Initialize(true);
        Backend.BMember.CustomLogin("a1", "a1");

        InvokeRepeating("PrintTime", 1.0f, 1.0f);
        InvokeRepeating("GetServerTimeFor5minutes", 300f, 300f); // 300초 뒤에 실행 300초마다 반복

        InitTime();
    }

    void InitTime() // 로그인 이후 서버 타임을 가져오는 함수. 최대 3번 실행
    {
        if (initTimeCount > 3)
        {
            Debug.LogError("시간을 3번 이상 불러올 수 없었습니다");
            return;
        }

        Backend.Utils.GetServerTime(callback =>
        {
            if (callback.IsSuccess())
            {
                string time = callback.GetReturnValuetoJSON()["utcTime"].ToString();
                serverTime = TimeZoneInfo.ConvertTimeToUtc(System.DateTime.Parse(time)).AddHours(9); // 현재 시간을 utc+0로 저장

                isChangeServerTime = true;
                isServerTimeUpdate = true;
            }
            else
            {
                initTimeCount++;
                InitTime();
            }
        });
    }

    void Update()
    {
        Backend.AsyncPoll();
    }

    private void FixedUpdate()
    {
        if (isServerTimeUpdate)
        {
            TimeUpdate();
        }
    }

    void TimeUpdate() // 시간을 업데이트 해주는 함수(FixedUpdate에서 실행해야함)
    {
        if (isChangeServerTime)
        {
            oldTime = Time.fixedUnscaledTime;
            currentTime = serverTime;
            isChangeServerTime = false;
        }

        var delta = Time.fixedUnscaledTime - oldTime;
        oldTime = Time.fixedUnscaledTime;

        currentTime = currentTime.AddMilliseconds(delta * 1000.0f);
    }

    private void PrintTime() // 시간 차이를 비교해주는 테스트를 위한 함수
    {
        Backend.Utils.GetServerTime(callback =>
        {
            if (callback.IsSuccess())
            {
                string time = callback.GetReturnValuetoJSON()["utcTime"].ToString();

                utcTime = TimeZoneInfo.ConvertTimeToUtc(System.DateTime.Parse(time)).AddHours(9); // 현재 시간을 utc+0로 저장
                Debug.Log($"Now: {utcTime}, myTime: {currentTime}");
            }
        });
    }

    private void GetServerTimeFor5minutes() // 5분마다 호출하는 함수
    {
        Backend.Utils.GetServerTime(callback =>
        {
            if (callback.IsSuccess())
            {
                string time = callback.GetReturnValuetoJSON()["utcTime"].ToString();
                serverTime = TimeZoneInfo.ConvertTimeToUtc(System.DateTime.Parse(time)).AddHours(9); // 현재 시간을 utc+0로 저장

                isChangeServerTime = true;
            }
        });
    }
}

답변 감사드립니다!. 해당 로직은 유용하게 잘 쓰겠습니다.

만약 위와 같이 로직을 구현 할 경우 저번처럼 서버에서 시간을 가져오는 함수호출이 실패가 되면

상황은 기존 로직과 동일하게 서버에러가 리턴되겠네요…ㅠㅠ

호출에러 3번~4번의 작은 정도는 감수가 되지만 저번처럼 장시간 에러가 나면 난처할것같습니다