[뒤끝팁] 길드원 실시간 접속 상태, 인게임에 구현하는 법

길드는 이미 오래전, 모바일 게임의 핵심 콘텐츠가 되었습니다. 커뮤니티를 중요시하는 온라인 게임에서는 길드 시스템은 필수 요소인데요?

‘길드’ 콘텐츠는 왜 대세가 되었을까요?

바로 유저와 유저의 관계를 이어주는, ‘커뮤니티’의 기능을 담당하기 때문입니다.

그렇다면 오늘 다루게 될 내용,
“실시간 접속 유저 표시는 왜 필요할까요?? “

실시간 접속 유저 표시는 길드의 핵심 포인트인 ‘커뮤니티’의 기능을 강화하는 장치이기 때문이예요.

현재 접속 중인 유저들끼리의 소통을 가능하게 하여, 유저가 게임에 더 몰입할 수 있게 만듭니다.
그리고 이는 곧 유저가 게임이 ‘재미있다’고 느끼는 요소가 되지요.

길드원 접속 시간을 보여주는 실제 인게임 화면

위 이미지처럼 우리 길드원이 접속 중인지, 몇 분 전에 접속을 했는지 어떻게 보여줄 수 있을까요?

① 길드원 목록 불러오기
② 실시간 알림 기능

뒤끝의 두 가지 기능을 활용하면, 유저의 접속 상태를 인 게임에서 실시간으로 노출할 수 있습니다!


유저의 접속 상태를 분류해 인 게임에 표시하는 알고리즘은 다음과 같아요.

유저의 접속 상태를 인게임에 표시하는 알고리즘

우리도 위 알고리즘을 따라서 구현 방법을 알아보겠습니다.
* 위 이미지에 기재된 번호(1, 2, 3)와, 아래 본문의 번호를 함께 맞춰서 보시면 더 이해하기 좋아요!?

1. 길드원 리스트 불러오기

뒤끝 SDK 5.5.0부터 친구 또는 길드원을 조회할 때, 최종 접속일이 함께 표시되도록 업데이트되었어요!

우선 길드원 리스트를 불러옵니다. 그리고 그곳에서 아래 데이터를 가져와야 해요.

① 접속 여부를 확인할 유저 ID: inDate
② 최근 접속일: lastLogin

유저의 리스트를 받아오는 함수(Backend.Social.Guild.GetGuildMemberListV3(string guildIndate))
리턴값은 다음과 같습니다.

{
    rows:
    [
        // 길드원 1
        {
            // 길드원 1의 굿즈 2 기부(+사용) 총량
            totalGoods2Amount:{ N:"21" },
            // 길드원 1의 굿즈 3 기부(+사용) 총량
            totalGoods3Amount:{ N:"8" },
            // 길드원 1 닉네임
            nickname:{ S:"id2" },
            // 길드원 1의 길드 indate (길드 가입 시점)
            inDate:{ S:"2018-11-21T05:42:24.511Z" },
            // 길드원 1 indate
            gamerInDate:{ S:"2018-11-08T03:32:18.210Z" },
            // 길드원 1 길드 권한 (master/viceMaster/member)
            position:{ S:"master" },
            //마지막으로 접속한 날짜
            lastLogin:{S:"2021-07-23T07:42:01.019Z"}
        },
        // 길드원 2
        {
            totalGoods2Amount:{ N:"0" },
            totalGoods3Amount:{ N:"0" },
            inDate:{ S:"2018-11-22T05:45:11.638Z" },
            gamerInDate:{ S:"2018-11-13T01:46:25.323Z" },
            totalGoods1Amount:{ N:"0" },
            position:{ S:"member" },
            lastLogin:{S:"2021-07-22T01:49:01.019Z"}
        },
    ],
   //firstKey가 존재할 경우
   firstKey:{"inDate":{"S":"2021-07-15T01:18:02.841Z"}}
   //firstKey가 존재하지 않을 경우
   firstKey:null
}

그러므로 다음과 같이 코드를 작성하면 길드 유저의 모든 최종 접속 일자를 알 수 있습니다.

var bro = Backend.Social.Guild.GetMyGuildInfoV3();

if(bro.IsSuccess())
{
   string myGuildIndate = bro.GetFlattenJSON()["guild"]["inDate"].ToString();
   
   var memberBro = Backend.Social.Guild.GetGuildMemberListV3(myGuildIndate);
   
   LitJson.JsonData json = memberBro.FlattenRows();
   
   int maxMemberCount = json.Count;

   for(int i = 0; i < maxMemberCount; i++)
   {
      string nick = json[i]["nickname"].ToString();
			string userIndate = json[i]["gamerInDate"].ToString();
      string lastLogin = json[i]["lastLogin"].ToString();
      Debug.Log(string.Format("닉네임 : {0} / 최종접속일자 : {1}",nick, lastLogin));
   }
}

이제 1번에서 불러온 데이터를 통해, 유저의 접속 여부를 확인해 줍니다. (2번)

이 작업은 뒤끝의 [실시간 알림] 기능으로 간단하게 진행할 수 있어요.

2. 접속 중인 유저 확인하기 (1번에서 불러온 데이터로)

유저는 현재 접속 중인가? ? Yes or No

[실시간 알림] 기능을 통해 유저의 접속 여부를 확인할 수 있습니다.

방법은 아주 간단한데요, 그저 함수 Connect()를 통해 실시간 알림 서버에 연결만 해주면 됩니다.

❗ 주의사항
실시간 알림은 다른 뒤끝 베이스의 기능들처럼 요청과 응답이 한곳에서 발생하지 않아요.
뒤끝챗, 뒤끝 매치와 같이 요청한 함수와 그에 응답하는 핸들러가 존재하며, 해당 핸들러를 
설정해 주어야 해요!

(1) 실시간 알림 활성화하기

활성화를 요청할 함수와 활성화 요청 후 응답되는 핸들러를 설정해 주세요.

bool isRealTimeAlarmActive = false;

void Start()
{
  // 핸들러를 등록해야하며 뒤끝 초기화 이후 게임이 종료될때까지 한번만 호출하면 됩니다
  Backend.Notification.OnAuthorize = (bool Result, string Reason) => {
        Debug.Log("실시간 서버 성공 여부 : " + Result);
        Debug.Log("실패 시 이유 : " +  Reason);
        isRealTimeAlarmActive  = Result;     
   };
  Backend.Notification.OnDisconnect = (string Reason) => {
    Debug.Log(Debug.Log("해제 이유 : " + Reason);
    isRealTimeAlarmActive = false;
};
}

void StartRealTimeAlarm()
{
  Backend.Notification.Connect();
}

StartRealTimeAlarm을 호출하면 OnAuthorize에 설정한 코드를 통해 “실시간 서버 성공 여부”를 확인하실 수 있습니다. 만약 Result가 True로 반환이 된다면 활성화에 성공한 것입니다!

(2) 해당 유저가 접속 중인지 확인하기

실시간 알림 기능 중에는 해당 유저가 실시간 알림 서버에 접속 중인지(실시간 알림이 활성화) 되어 있는지 확인하는 함수가 있는데요.

만약 로그인 이후 모든 유저가 실시간 알림 서버에 접속한다는 가정 하에, 이 함수를 이용하면 현재 유저가 게임에 접속 중인지 확인할 수 있습니다.


void Start()
{
   // UserIsConnectByIndate 함수 호출 시 반응하는 OnIsConnectUser 핸들러를 설정한다.
   Backend.Notification.OnIsConnectUser= (bool isConnect, string nickName, string gamerIndate) => {
       Debug.Log($"{nickName} / {gamerIndate} 접속 여부 확인 : {isConnect}");
   };
}

void CheckUserIsActive(string gamerIndate)
{
  // 함수 호출 시, 위에서 설정한 OnIsConnectUser 핸들러가 호출된다.
  Backend.Notification.UserIsConnectByIndate(gamerIndate);
}

CheckUserIsActive을 호출하면 OnIsConnectUser에 설정한 코드를 통해 해당 nickname과 gamerIndate의 접속 여부 isConnect를 확인하실 수 있습니다.

3. 인게임에서 표시되도록 구현하기!

1번과 2번에서, 최종 접속일과 유저 접속 여부를 확인하는 방법을 알아보았습니다. 이 두 가지를 적절히
활용하면 ‘길드원 접속 상태’를 게임에서 노출할 수 있어요.

다음과 같은 프로세스를 통해 개발을 하실 수 있습니다.

① 길드원의 정보를 불러와 Dictionary(Map)에 저장하기
② 저장된 Dictionary에 있는 모든 유저가 접속 중인지 for문을 통해 확인하기
③ 접속 중이라면 ‘온라인’, 접속 중이 아니라면 ‘오프라인’ 표시 후 현재 시간과 최종 접속일을 빼서 마지막 접속일을 표현하기

(1) 길드 유저 정보를 담을 클래스 생성

public class GuildMemberInfo
{
    public string nickname = ""; // 유저의 닉네임
    public string indate = ""; // 유저의 inDate
    public DateTime lastLogin; // 마지막 접속 시간
    public string lastLoginString = ""; //마지막 접속 시간 표시
    public bool isActive = false; // 현재 게임에 접속중인지(실시간알림 서버에 접속했는지)
    
    //생성자
    public GuildMemberInfo(string _indate, string _nickname, string _lastLogin)
    {
        this.indate = _indate;
        this.nickname = _nickname;
        this.lastLogin = DateTime.Parse(_lastLogin);

        SetLastLoginString(this.lastLogin);
    }

    // 접속시간을 표시해주는 string을 설정해준다.(현재시간 - 마지막 접속 시간)
    void SetLastLoginString(DateTime time)
    {
        TimeSpan ts = DateTime.Now - time;
        if (ts.Days > 0)
        {
            lastLoginString = $"{ts.Days}일 전";
        }
        else if (ts.Hours > 0)
        {
            lastLoginString = $"{ts.Hours}시간 전";
        }
        else if (ts.Minutes > 0)
        {
            lastLoginString = $"{ts.Minutes}분 전";
        }
        else
        {
            lastLoginString = $"방금 전";
        }
    }

		void ChangeActive(bool _isActive) // 접속중인지 설정
    {
       this.isActive = _isActive;
			 if(this.isActive)
       {
          lastLoginString = "온라인";
       }
       //UI적으로 온라인이면 초록불 또는 오프라인이면 회색불등의 값이 바뀌도록 설정해준다.

    }

    public override string ToString()
    {
        //string.Format("inDate : {0} / 닉네임 : {1} / 최종접속일자 : {2} / 접속중 : {3}", indate, nickname, lastLogin, isActive);

        if (isActive)
        {
            return string.Format("닉네임 : {0}  온라인", nickname);
        }
        else
        {
            return string.Format("닉네임 : {0} 오프라인 {1}", nickname, lastLoginString);

        }
    }
}

(2) 유저의 리스트를 불러와 최종 접속일 체크, 접속 중인지 확인

//길드 유저를 담아놓기 위한 Dictionary(Map)
//Key값을 유저의 고유값인 inDate로 하는 것을 추천
Dictionary<string, GuildMemberInfo> guildMember = new Dictionary<string, GuildMemberInfo>();

enum USERCHECK // OnIsConnectUser 사용시 어떤 동작인지 구별하기 위한 ENUM
{
    NONE,
    FRIEND,
    GUILD
}
USERCHECK userCheck = USERCHECK.NONE; // enum 초기화

void SetGuildMemberInfo()
{
    userCheck = USERCHECK.GUILD; // 길드 호출시 GUILD 유저 접속중인지 상태값 변경(친구창을 구현한다면 USERCHECK.FRIEND)
    
		Backend.Notification.OnIsConnectUser = (bool isConnect, string nickName, string gamerIndate) => // 핸들러 설정
    {
        //Debug.Log($"{nickName}({gamerIndate}) 님의 접속 여부 : {isConnect}");
        
        if (guildMember.ContainsKey(gamerIndate))
        {
            guildMember[gamerIndate].ChangeActive(isConnect); // 접속 여부 적용
        }
    };

    var bro = Backend.Social.Guild.GetMyGuildInfoV3(); // 내 길드 정보 불러오기
    
		if (bro.IsSuccess())
    {
        string myGuildIndate = bro.GetFlattenJSON()["guild"]["inDate"].ToString(); // 내 길드의 inDate 가져오기
        
				var memberBro = Backend.Social.Guild.GetGuildMemberListV3(myGuildIndate); // 길드 멤버 불러오기
        
				LitJson.JsonData json = memberBro.FlattenRows(); // json으로 변환
        int maxMemberCount = json.Count; // 길드 멤버 수 확인
        
				for (int i = 0; i < maxMemberCount; i++) // 
        {
            string nick = json[i]["nickname"].ToString(); // 닉네임 가져오기
            string indate = json[i]["gamerInDate"].ToString(); // inDate 가져오기
            string lastLogin = json[i]["lastLogin"].ToString(); // 최종접속일 확인하기
            GuildMemberInfo info = new GuildMemberInfo(indate, nick, lastLogin); // 길드 멤버 정보 생성
            guildMember.Add(indate, info); // inDate(고유 id)를 Key로 Dictionary에 추가
            Backend.Notification.UserIsConnectByIndate(indate); // 해당 유저가 접속중인지 확인
        }
				SetGuildMemberUI();
    }
}

(3) 설정된 길드 멤버 UI 적용

void SetGuildMemberUI()
{
    foreach(var obj in guildMember)
    {
       Debug.Log(obj.ToString());
			 //이외 게임 오브젝트들을 생성하여 UI로 표시해준다.
       //실시간 알림 기능은 비동기이기에 접속 여부 표시가 조금 뒤에 순차적으로 표시될 수 있다.
    }
}

지금까지 뒤끝의 두 가지 기능을 활용해서 ‘길드원 접속 상태’를 구현하는 방법을 알아보았습니다.

이러한 방식을 통해 3번에서 자신의 UI에 맞게 guildMember의 정보를 불러 사용하면 좀 더 활발한,
가족 같은 길드 커뮤니티를 형성할 수 있어요?

이제 개발자 님만의 멋진 길드를 만들어 보세요!

? 뒤끝 팁 : 같은 로직을 친구 목록에서도 활용할 수 있어요!

유저의 리스트를 받아오는 함수를 길드(Backend.Social.Guild.GetGuildMemberListV3
(string guildIndate))가 아닌 친구(Backend.Social.Friend.GetFriendList())로 
변경해 주시면 친구 목록도 손쉽게 구현 가능합니다!

단, 친구와 길드 간에 리턴되는 세세한 차이점들은 변경해 주는 센스! 챙겨주세요?

1

댓글