Unity之NetCode多人网络游戏联机对战教程(4)--连接申请ConnectionApproval

本文介绍了如何在Unity中使用Netcode进行在线游戏的连接审批过程,包括设置ConnectionApproval、创建GameManager脚本处理客户端请求、对象的预设体选择等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

没看过前面的教程请先阅读前面的教程,本期将会讲到Netcode联机的申请,当一个Client想连接进来,应向Server发送申请联机的信息,然后由服务端向客户端下发数据,所有数据应该在服务端,而不是在客户端。


适用场景

举几个常见的例子需要用到ConnectionApproval的场景

  • 使用密码加入房间
  • 玩家选择不同的角色
  • 房间人数
  • 各种需要服务端下发的信息等等

1. 准备

需要在第二期上添加多的一个Player预制体

每个Player都需要挂载上NetworkObject这个组件

最重要的一点是在NetworkManager上开启ConnectionApproval


2.新建GameManager

新建一个GameManager空物体,添加NetworkObject这个组件

Scripts目录下新建一个GameManager脚本,挂载到GameManager的空物体上

using UnityEngine;
using Unity.Netcode;
using System.Text;

public class GameManager : NetworkBehaviour
{
    public GameObject Man;
    public GameObject Girl;

    public override void OnNetworkSpawn()
    {
        if (IsServer)
        {
            NetworkManager.ConnectionApprovalCallback = ApprovalCheck;
        }
    }

    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.O))
        {
            NetworkManager.Singleton.NetworkConfig.PlayerPrefab = Man;
            NetworkManager.Singleton.StartHost();
        }

        if (Input.GetKeyDown(KeyCode.P))
        {
            NetworkManager.Singleton.NetworkConfig.ConnectionData = Encoding.UTF8.GetBytes("Girl");
            NetworkManager.Singleton.StartClient();
        }
    }

    private void ApprovalCheck(NetworkManager.ConnectionApprovalRequest request, NetworkManager.ConnectionApprovalResponse response)
    {
        // The client identifier to be authenticated
        var clientId = request.ClientNetworkId;

        // Additional connection data defined by user code
        var connectionData = request.Payload;

        var _character = Encoding.UTF8.GetString(connectionData);

        if (_character == "Girl")
        {
            response.PlayerPrefabHash = Girl.GetComponent<NetworkObject>().PrefabIdHash;
        }
        else
        {
            response.PlayerPrefabHash = Man.GetComponent<NetworkObject>().PrefabIdHash;
        }

        // Your approval logic determines the following values
        response.Approved = true;
        response.CreatePlayerObject = true;

        // Position to spawn the player object (if null it uses default of Vector3.zero)
        response.Position = Vector3.zero;

        // Rotation to spawn the player object (if null it uses the default of Quaternion.identity)
        response.Rotation = Quaternion.identity;

        // If response.Approved is false, you can provide a message that explains the reason why via ConnectionApprovalResponse.Reason
        // On the client-side, NetworkManager.DisconnectReason will be populated with this message via DisconnectReasonMessage
        response.Reason = "Some reason for not approving the client";

        // If additional approval steps are needed, set this to true until the additional steps are complete
        // once it transitions from true to false the connection approval response will be processed.
        response.Pending = false;
    }
}

Inspector窗口绑定一下两个角色到脚本中


3.编译运行

分别按下O键与P键,可以看到有两个不同的Player Prefab实例化了。


4.脚本详解

  • GameManager继承的是NetworkBehaviour而非MonoBehaviour

重写OnNetworkSpawn()方法,让NetworkManager放入回调方法ApprovalCheck让服务端处理

public override void OnNetworkSpawn()
    {
        if (IsServer)
        {
            NetworkManager.ConnectionApprovalCallback = ApprovalCheck;
        }
    }

ApprovalCheck这个回调方法传入两个类型的参数,分别是NetworkManager.ConnectionApprovalRequestNetworkManager.ConnectionApprovalResponse

  • NetworkManager.ConnectionApprovalRequest 是客户端的请求,一共两个字段
    ClientNetworkId 是客户端的唯一标识ID
    Payload是客户端发送的信息,封装成byte类型,这也是我们主要使用的
private void ApprovalCheck(NetworkManager.ConnectionApprovalRequest request, NetworkManager.ConnectionApprovalResponse response)
    {
        // The client identifier to be authenticated
        var clientId = request.ClientNetworkId;

        // Additional connection data defined by user code
        var connectionData = request.Payload;

        var _character = Encoding.UTF8.GetString(connectionData);

        if (_character == "Girl")
        {
            response.PlayerPrefabHash = Girl.GetComponent<NetworkObject>().PrefabIdHash;
        }
        else
        {
            response.PlayerPrefabHash = Man.GetComponent<NetworkObject>().PrefabIdHash;
        }

        // Your approval logic determines the following values
        response.Approved = true;
        response.CreatePlayerObject = true;

        // Position to spawn the player object (if null it uses default of Vector3.zero)
        response.Position = Vector3.zero;

        // Rotation to spawn the player object (if null it uses the default of Quaternion.identity)
        response.Rotation = Quaternion.identity;

        // If response.Approved is false, you can provide a message that explains the reason why via ConnectionApprovalResponse.Reason
        // On the client-side, NetworkManager.DisconnectReason will be populated with this message via DisconnectReasonMessage
        response.Reason = "Some reason for not approving the client";

        // If additional approval steps are needed, set this to true until the additional steps are complete
        // once it transitions from true to false the connection approval response will be processed.
        response.Pending = false;
    }
  • NetworkManager.ConnectionApprovalResponse是服务端给客户端的响应,一共有八个字段
    Approved:是否同意客户端加入
    Reason: 如果Approvedfalse,填写拒绝理由
    CreatePlayerObject 是否生成玩家实体
    PlayerPrefabHash 如果null则生成在NetworkManager默认的Player Prefab,这个值要填入NetworkObjectPrefabIdHash
    Position生成玩家实体的position
    Rotation生成玩家实体的rotation
    Pending 挂起approval延迟授权,直到其他客户端完成approval, 官方解释:Provides the ability to mark the approval as pending to delay the authorization until other user-specific code finishes the approval process.

后话

官方相关的阅读文档:

<think>好的,用户现在问的是Unity网络框架推荐。之前他问过如何实现局域网联机游戏,我推荐了Mirror,现在他可能想进一步了解其他可用的框架或者更全面的推荐。我需要先回顾之前的回答,确保一致性,同时补充更信息。 首先,用户可能是开发者,正在寻找适合自己项目的网络框架。他可能对Unity的网络解决方案不太熟悉,或者之前的项目需要扩展,想评估不同选项。我需要考虑他的使用场景:是制作小型游戏,还是大型MMO?不同的框架适用性不同。 之前的回答重点在Mirror,这次需要扩展其他框架。比如Unity自带的Netcode、光子Cloud、Fish-Net等。要比较它们的优缺点,适用场景,以及学习资源。 需要注意用户可能的隐藏需求:比如是否需要免费方案,是否需要托管服务,或者对P2P与服务器架构的选择。比如独立开发者可能更倾向免费和易用性,而商业项目可能需要可靠性和扩展性。 另外,用户可能对同步方式(权威服务器 vs 对等网络)、传输协议(TCP/UDP)、支持的平台等也有兴趣。需要简要说明每个框架的特点,帮助用户做出选择。 还要检查是否有新出现的框架或者旧框架的更新,比如MLAPI已经更名为Netcode,需要确保信息的准确性。同时,避免推荐过时或不再维护的库,比如UNet已经弃用,但Mirror作为替代方案仍然活跃。 最后,结构要清晰,分点列出每个框架,包括特点、适用场景和资源链接,便于用户快速比较。可能需要提醒用户根据项目规模、团队经验和需求来选择,比如小项目用Mirror或Netcode,大型项目考虑光子或专业解决方案。</think>以下是Unity主流网络框架的深度对比与推荐,根据项目类型和需求可选择不同方案: --- ### 一、官方解决方案 #### 1. **Unity Netcode (原MLAPI)** ```csharp // 官方示例代码 public class PlayerMovement : NetworkBehaviour { [ServerRpc] void MoveServerRpc(Vector3 newPosition) { transform.position = newPosition; } } ``` - **特点**: - 官方维护的跨平台方案(支持PC/主机/移动端) - 支持**100+玩家**的实时同步 - 集成NGONetcode for GameObjects)组件化系统 - **适用场景**:中小型游戏(如《Among Us》类游戏) - **资源**:[Netcode官网](https://unity.com/products/netcode) #### 2. **Unity Relay 服务** - 云端P2P中转服务 - 免费额度:每月**1,000 CCU** - 无需自建服务器,适合独立开发者 --- ### 二、第三方开源框架 #### 1. **Mirror (推荐)** ```csharp // 玩家同步示例 [Command] // 客户端->服务端 void CmdShoot() { // 服务端验证射击逻辑 RpcShowMuzzleFlash(); // 广播给所有客户端 } ``` - **优势**: - 完全开源且持续更新 - 支持**WebGL**的WebSocket协议 - 自带房间匹配系统 - **性能**:支持**50-80**实时对 - **学习曲线**:⭐️⭐️(适合Unity开发者快速上手) #### 2. **Fish-Net** - **亮点**: - 支持**10,000+** 实体同步(MMO级) - 预测回滚算法优化 - 内置对象池和序列化压缩 - **测试数据**:500玩家场景延迟<200ms --- ### 三、商业解决方案 #### 1. **Photon引擎** ```csharp // Photon RPC调用 [PunRPC] void OnPlayerHit(int damage) { currentHealth -= damage; } ``` - **方案对比**: | 版本 | 最大CCU | 价格模型 | 适用类型 | |-----------|--------|-------------|-------------| | Photon PUN| 20免费 | 按CCU阶梯收费 | 休闲竞技游戏 | | Photon Quantum | 无上限 | 定制报价 | 电竞级实时游戏 | - **独特优势**:全球分布式服务器,亚洲节点延迟<80ms #### 2. **Nakama** - 开源服务器框架 - 支持**社交系统**(好友/成就/排行榜) - 自带数据库和实时聊天 --- ### 四、选型决策树 1. **项目规模**: - 小型项目:Mirror/Netcode - 中大型项目:Photon/Fish-Net - MMO:Fish-Net + 自研服务器 2. **网络模型需求**: ```mermaid graph TD A[选择网络架构] --> B{需要服务器权威?} B --> |是| C[Photon/Netcode] B --> |否| D[Mirror P2P] ``` 3. **预算考量**: - **零成本**:Mirror + 自建服务器 - **商业授权**:Photon($95/月起) --- ### 五、性能优化建议 1. **同步频率控制**: ```csharp [SyncVar(updateInterval = 0.1f)] private Vector3 _position; ``` 2. **带宽压缩**: - 使用`BitStream`压缩数据包 - 坐标精度控制:`0.001f` 3. **预测算法**: - 客户端预测 + 服务器校正 - 插值平滑处理 --- ### 六、学习路径推荐 1. **入门**:Unity Learn游戏课程(免费) 2. **进阶**:《Networked Games in C#》(书籍) 3. **实**:开发一个简单的大厅匹配系统(需处理NAT穿透) 各框架文档入口: - Mirror:https://mirror-networking.com/ - Netcode:https://docs-multiplayer.unity3d.com/ - Photon:https://doc.photonengine.com/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值