说明

希望有生之年能在Steam发售一款无服务器的联机游戏。
在寻找解决方案时找到了Mirror,不过好像已经停止更新了。故而寻找新的替代品,此时,FishNet进入了我的视野。FishNet拥有非常活跃的社区以及解决方案。在FishNet的基础上,使用社区扩展的FishySteamworks进行连接的扩展,可以不需要通过外网IP也可以直接通过Steam进行数据交换。

项目引用

FishNet
Steamworks.NET
FishySteamworks

简单例子

  1. 导入包后,在包里找到NetworkManager,直接丢入场景。
  2. 创建一个游戏对象,附加NetworkObjectNetworkTransform,拖入NetworkManagerPlayerSpawnerPlayerPrefabs
  3. 启动后可以看到服务器和客户端的按钮,启动服务器后启动客户端即可看到玩家预制体被克隆出来,从局域网启动就可以了。
  4. 连接Steam还需要在NetworkManager附加FishySteamworks组件,该组件是继承自FishNet的连接组件Transport。还需要编写SteamSDK的相关代码如下:
#if UNITY_STANDALONE_WIN
/*********************************************
 * BFramework
 * SteamSDK工具类
 * 创建时间:2023/12/27 17:43:00
 *********************************************/
using FishySteamworks;
using Framework;
using Steamworks;
using System;

namespace GameData
{
    /// <summary>
    /// SteamSDK工具类
    /// </summary>
    public class SteamSDKHelper : GameBase
    {
        /// <summary>
        /// Steam和FishNet网络中转器
        /// </summary>
        private FishySteamworks.FishySteamworks _fishySteamworks;
        public void InitFishySteamworks(FishySteamworks.FishySteamworks fishySteamworks) => _fishySteamworks = fishySteamworks;

        private const string _hostAddressKey = "HostAddress";
        private string _hostAddressValue;

        public SteamSDKHelper()
        {
            InitSteamCallback();
        }

        #region Callback
        /// <summary>
        /// 创建大厅回调
        /// </summary>
        private Callback<LobbyCreated_t> _lobbyCreatedCallback;
        /// <summary>
        /// 从大厅加入游戏的回调
        /// </summary>
        private Callback<GameLobbyJoinRequested_t> _gameLobbyJoinRequestedCallback;
        /// <summary>
        /// 加入大厅后的回调
        /// </summary>
        private Callback<LobbyEnter_t> _lobbyEnterCallback;

        /// <summary>
        /// 初始化Steam监听回调
        /// </summary>
        private void InitSteamCallback()
        {
            _lobbyCreatedCallback = Callback<LobbyCreated_t>.Create(LobbyCreatedCallback);
            _gameLobbyJoinRequestedCallback = Callback<GameLobbyJoinRequested_t>.Create(GameLobbyJoinRequestedCallback);
            _lobbyEnterCallback = Callback<LobbyEnter_t>.Create(LobbyEnterCallback);
        }

        /// <summary>
        /// 创建大厅回调
        /// </summary>
        private void LobbyCreatedCallback(LobbyCreated_t result)
        {
            if (result.m_eResult != EResult.k_EResultOK)
            {
                LogError("Steam大厅创建失败!");
                return;
            }
            Log("Steam大厅创建成功!");

            //设置大厅数据
            _hostAddressValue = SteamUser.GetSteamID().ToString();
            SteamMatchmaking.SetLobbyData(new CSteamID(result.m_ulSteamIDLobby), _hostAddressKey, _hostAddressValue);
            _fishySteamworks.SetClientAddress(_hostAddressValue);
            _fishySteamworks.StartConnection(true);
        }

        /// <summary>
        /// 从好友列表中加入大厅时调用
        /// </summary>
        private void GameLobbyJoinRequestedCallback(GameLobbyJoinRequested_t result)
        {
            SteamMatchmaking.JoinLobby(result.m_steamIDLobby);
            Log("Steam好友尝试从好友列表加入!");
        }

        /// <summary>
        /// 加入大厅后的回调
        /// </summary>
        private void LobbyEnterCallback(LobbyEnter_t result)
        {
            string hostAddress = SteamMatchmaking.GetLobbyData(new CSteamID(result.m_ulSteamIDLobby), _hostAddressKey);
            _fishySteamworks.SetClientAddress(hostAddress);
            _fishySteamworks.StartConnection(false);
        }

        #endregion

        /// <summary>
        /// 创建大厅
        /// </summary>
        public void CreateLobby()
        {
            if (!SteamManager.Initialized)
            {
                LogError("Steam未初始化");
                return;
            }
            SteamMatchmaking.CreateLobby(ELobbyType.k_ELobbyTypeFriendsOnly, GameData.ConstDefine.RoomMaxPeople);
        }
    }
}
#endif

  1. 到此,用户创建或连接Steam大厅并进行数据同步就大功告成了。

已知问题

FishNet所有的脚本,如果使用AB包克隆会丢失记录UID的表对象(原因不明),而Resource加载不会。所以不支持AB包以及代码热更新(?)。

最后修改:2024 年 05 月 16 日
如果觉得我的文章对你有用,请随意赞赏