ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 유니티 스팀 멀티 연동하기 - 5. 게임 내 초대 구현
    Unity 2023. 10. 13. 22:01
    728x90

    스팀에서 실행한 게임은, 게임 도중 Shift + Tab 키를 누르면 스팀 오버레이가 펼쳐지며 친구를 초대할 수 있다.

    하지만, 스팀을 오래하지 않거나, 멀티가 익숙하지 않은 사람은 이런 초대 방법을 모를 수 있다.

    그렇기 때문에 대부분의 게임에서는 스팀 오버레이 없이 게임 내에서 초대하는 기능을 따로 또 넣고는 한다.

     

    이 기능은 스팀 구현은 정보가 거의 없어서 API 도큐먼트를 직접 읽으면서 찾을 수밖에 없었다.

    아래는 스팀 친구 초대 UI 패널을 띄울 때 친구 목록을 가져오고 생성하는 부분을 잘라온 것이다.

        private void UpdateFriendList()
        {
            var c = content.GetComponentsInChildren<Transform>();
            c.ToList().ForEach(x =>
            {
                if(x != content)
                    Destroy(x.gameObject);
            });
    
            List<Steamworks.CSteamID> friendsList = new List<Steamworks.CSteamID>();
            
            int friendCount = Steamworks.SteamFriends.GetFriendCount(Steamworks.EFriendFlags.k_EFriendFlagImmediate);
            for(int i = 0; i < friendCount; i++)
            {
                var friend = Steamworks.SteamFriends.GetFriendByIndex(i, Steamworks.EFriendFlags.k_EFriendFlagImmediate);
    
                if(Steamworks.SteamFriends.GetFriendPersonaState((Steamworks.CSteamID)friend.m_SteamID) != Steamworks.EPersonaState.k_EPersonaStateOffline)
                {
                    GameObject obj = Instantiate(prefabPanelInviteItem, content, false);
                    var controller = obj.GetComponent<PanelInviteItemController>();
                    controller.PlayerSteamID = friend.m_SteamID;
                    controller.PlayerName = Steamworks.SteamFriends.GetFriendPersonaName((Steamworks.CSteamID)friend.m_SteamID);
                    controller.PlayerNameText.text = controller.PlayerName;
    
                    friendsList.Add(friend);
                }
    
                
            }
            Debug.Log($"Steam friend Count : {friendsList.Count}");
    
    
        }

     

    Steamworks.SteamFriends.GetFriendCount를 통해 가져올 친구의 숫자를 받아올 수 있다.

    물론 패러미터로 가져올 친구의 조건을 필터링할 수 있다.

    위에 나온대로 EFriendFlags를 입맛에 맞게 변경해주면 된다.

    본인의 스팀 이름이 아닌, 친구의 이름을 가져오는 방법도 찾기가 좀 어려웠는데, Steamworks.SteamFriends.GetFriendPersonaName()을 사용해서 가져올 수 있고, 해당 친구의 스팀ID 값을 패러미터로 넣어주면 된다.

     

    구현시 친구의 설정해놓은 아바타 사진을 가져와서 보여주고 싶다면, 아래의 리스트 아이템에 넣은 스크립트 예시를 고쳐 사용하면 된다.

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    using Steamworks;
    using System;
    
    public class PanelInviteItemController : MonoBehaviour
    {
        public string PlayerName;
        public int ConnectionID;
        public ulong PlayerSteamID;
        private bool AvatarReceived;
    
        public Text PlayerNameText;
        public RawImage PlayerIcon;
    
        [SerializeField]
        private Button buttonInvite;
    
        protected Callback<AvatarImageLoaded_t> ImageLoaded;
    
        private void Start()
        {
            ImageLoaded = Callback<AvatarImageLoaded_t>.Create(OnImageLoaded);
            buttonInvite.onClick.AddListener(() =>
           {
               //SteamFriends.InviteUserToGame((CSteamID)PlayerSteamID, SteamLobby.Instance.CurrentLobbyID.ToString());
               SteamMatchmaking.InviteUserToLobby((CSteamID)SteamLobby.Instance.CurrentLobbyID, (CSteamID)PlayerSteamID);
           });
            SetPlayerValues();
        }
    
        private void OnImageLoaded(AvatarImageLoaded_t callback)
        {
            Debug.Log($"PlayerSteamID : {PlayerSteamID}");
            if(callback.m_steamID.m_SteamID == PlayerSteamID)
            {
                PlayerIcon.texture = GetSteamImageAsTexture2D(callback.m_iImage);
            }
            else//another player
                return;
        }
    
        void GetPlayerIcon()
        {
            
            int ImageID = SteamFriends.GetLargeFriendAvatar((CSteamID)PlayerSteamID);//SteamFriends.GetSmallFriendAvatar((CSteamID)PlayerSteamID); //
            if (ImageID == -1)
            {
                Debug.Log($"no profile image : {(CSteamID)PlayerSteamID}");
                return;
            }
                
            PlayerIcon.texture = GetSteamImageAsTexture2D(ImageID);
        }
    
        public void SetPlayerValues()
        {
            PlayerNameText.text = PlayerName;
            if (!AvatarReceived)
                GetPlayerIcon();
        }
    
        private Texture2D GetSteamImageAsTexture2D(int iImage)
        {
            Texture2D ret = null;
            uint ImageWidth;
            uint ImageHeight;
            bool bIsValid = SteamUtils.GetImageSize(iImage, out ImageWidth, out ImageHeight);
    
            if (bIsValid)
            {
                byte[] Image = new byte[ImageWidth * ImageHeight * 4];
    
                bIsValid = SteamUtils.GetImageRGBA(iImage, Image, (int)(ImageWidth * ImageHeight * 4));
                if (bIsValid)
                {
                    ret = new Texture2D((int)ImageWidth, (int)ImageHeight, TextureFormat.RGBA32, false, true);
                    ret.LoadRawTextureData(Image);
                    ret.Apply();
                }
            }
    
            return ret;
        }
    
    }

     

    SteamFriends.GetLargeFriendAvatar()로 이미지ID값을 찾고, SteamUtils.GetImageRGBA()를 사용해서 가져올 수 있다.

    byte[] 형식으로 가져오므로, 사이즈에 맞춰 RawTexture로 변환해 사용하면 된다.

    테스트했을 때, 막상 구현해놨는데 이미지가 뒤집어져 나오면 이상한 게 아니고 정상이다.

    데이터값 자체를 뒤집어주는 방법도 있겠지만, 복잡한 구현 없이 게임 내 Image를 rotation z값을 180도 돌리고, Scale x값을 -1로 변경해서 사용하면 편하다.

     

    728x90

    댓글

Designed by Tistory.