首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Unity 多人游戏框架学习系列三

Unity 多人游戏框架学习系列三

作者头像
心疼你的一切
发布2026-01-20 15:43:24
发布2026-01-20 15:43:24
1140
举报
文章被收录于专栏:人工智能人工智能

前言

接上一篇的继续分解

博客将会介绍多人游戏学习。希望这篇博客对Unity的开发者有所帮助。 大家好,我是心疼你的一切,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 欢迎点赞评论哦.下面就让我们进入正文吧 !


提示:以下是本篇文章正文内容,下面案例可供参考

一、游戏状态管理

网络多人游戏可在三种模式下运行,即作为客户端、作为专用服务器或作为“主机”(同时充当客户端和服务器)。

如果使用 Network Manager HUD 组件,该组件会根据玩家选择的选项自动告知 Network Manager 启动哪种模式。如果要自己编写允许玩家启动游戏的 UI,必须使用自己的代码调用这些 UI。这些方法是:

  • NetworkManager.StartClient
  • NetworkManager.StartServer
  • NetworkManager.StartHost
在这里插入图片描述
在这里插入图片描述

无论游戏以何种模式(客户端、服务器还是主机)启动,都会使用 Network Address 和 Network Port 属性。在客户端模式下,游戏尝试连接到指定的地址和端口。在服务器或主机模式下,游戏会监听指定端口上的传入连接。

1-1、使用 Network Manager HUD

在这里插入图片描述
在这里插入图片描述

|

属性

功能

Show Runtime GUI

勾选此复选框可在运行时显示 Network Manager HUD GUI。这样可以显示或隐藏此 GUI 以便快速调试。

GUI Horizontal Offset

设置 HUD 的水平像素偏移(从屏幕左边缘开始测量)。

GUI Vertical Offset

设置 HUD 的垂直像素偏移(从屏幕顶部边缘开始测量)。

Network Manager HUD(“抬头显示”)提供的基本功能可让游戏玩家开始托管联网游戏,或者查找并加入现有的联网游戏。Unity 将 Network Manager HUD 显示为 Game 视图中的简单 UI 按钮的集合。

在这里插入图片描述
在这里插入图片描述

Network Manager HUD 是一种快速启动工具,有助于立即开始构建多人游戏,而无需首先构建用于创建/连接/加入游戏的用户界面。使用该组件后,可直接进入游戏编程阶段,然后在开发计划的后期再构建这些控件的自定义版本。

但是,该组件并不适合用在已完成的游戏中。根据该组件的设计意图,这些控件对于开发初期很有用,但在开发后期应创建自定义 UI,让玩家能使用适合具体游戏的界面来查找和加入游戏。例如,您可能希望在风格方面调整屏幕、按钮和可用游戏列表的设计,使之符合游戏的整体风格。

在开始使用 Network Manager HUD 之前,请在场景中创建一个空游戏对象(菜单:GameObject > Create Empty),并将 Network Manager HUD 组件添加到新游戏对象。

有关 Network Manager HUD Inspector 中显示的属性的说明,请参阅 Network Manager HUD 参考页面。

1-2、使用HUD

Network Manager HUD 有两种基本模式:LAN(局域网)模式和 Matchmaker 模式。这些模式匹配两种常见类型的多人游戏。LAN 模式用于创建或加入托管在局域网上的游戏(即连接到同一网络的多台计算机),而 Matchmaker 模式用于在互联网上创建、查找和加入游戏(连接到不同网络的多台计算机)。

Network Manager HUD 默认处于 LAN 模式,并显示一些与托管和加入 LAN 模式多人游戏相关的按钮。要将 HUD 切换到 Matchmaker 模式,请单击 Enable Match Maker (M) 按钮。

注意:请记住,Network Manager HUD 功能是针对开发的临时辅助功能。此组件允许您快速运行多人游戏,但在准备就绪之后应将其替换为您自己的 UI 控件。

二、开始位置

要控制玩家的生成位置,可使用 Network Start Position 组件。要使用 Network Start Position 组件,请将其附加到场景中的游戏对象,并将该游戏对象放置在希望某一个玩家开始的位置。可根据需要为场景添加任意数量的起始位置。Network Manager 会检测场景中的所有起始位置,并在生成每个玩家实例时使用其中一个位置和方向。

Network Manager 具有 Player Spawn Method 属性,用于配置如何选择起始位置。

选择 Random 可根据随机选择的 startPosition 选项生成玩家。

选择 Round Robin 可循环使用预设列表中的 startPosition 选项。

如果 Random 或 Round Robin 模式不符合游戏需求,可使用代码自定义如何选择起始位置。可通过 NetworkManager.startPositions 列表访问可用的 Network Start Position 组件,并可使用 Network Manager 上的 helper 方法 GetStartPosition(),该方法可用于实现 OnServerAddPlayer 以便查找起始位置。

场景管理

大多数游戏都有多个场景。至少,除了实际进行游戏的场景之外,通常还有标题屏幕或开始菜单场景。Network Manager 旨在以适合多人游戏的方式自动管理场景状态和场景转换。

NetworkManager Inspector 上有两个用于场景的字段:Offline Scene 和 Online Scene。将场景资源拖动到这些字段中可激活联网场景管理。

启动服务器或主机时将加载联机场景 (Online Scene)。然后,此场景将成为当前的网络场景。连接到该服务器的所有客户端都被要求也加载此场景。此场景的名称存储在 networkSceneName 属性中。

网络停止(通过停止服务器或主机或者通过断开客户端连接)时将加载脱机场景 (Offline Scene)。因此,游戏在与多人游戏断开连接时会自动返回菜单场景。

还可以通过调用 NetworkManager.ServerChangeScene() 在游戏处于活动状态时更改场景。这样也会使所有当前连接的客户端改变场景,并更新 networkSceneName,让新客户端也能加载新场景。

联网场景管理处于激活状态时,对游戏状态管理函数(如 NetworkManager.StartHost() 或 NetworkManager.StopClient())的任何调用都可能导致场景改变。此规则适用于运行时控件 UI。通过设置场景并调用这些方法,可控制多人游戏的流程。

请注意,场景改变会导致前一个场景中的所有游戏对象都被销毁。

通常应确保 Network Manager 在场景之间保持不变,否则在场景改变时网络连接会中断。为此,请确保在 Inspector 内选中 Don’t Destroy On Load 复选框。但是,也可在每个场景中使用具有不同设置的单独 Network Manager,如果希望控制增量预制件加载或不同的场景转换,可能会很有用。

自定义

NetworkManager 类上有一些可自定义的虚拟函数;您可以通过自行创建继承自 NetworkManager 的派生类来自定义这些函数。实现这些函数时,请务必注意默认实现所提供的功能。例如,在 OnServerAddPlayer() 中,必须调用函数 NetworkServer.AddPlayer 来激活要连接的玩家游戏对象。

以下是主机/服务器和客户端可能发生的所有回调,在某些情况下,调用基类函数来维持默认行为很重要。要查看实现本身,可在 Bitbucket Networking 代码仓库中进行查看。

代码如下:

代码语言:javascript
复制
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Networking.Match;

public class CustomManager : NetworkManager {
    // 服务器回调
    public override void OnServerConnect(NetworkConnection conn) {
        Debug.Log("A client connected to the server: " + conn);
    }

    public override void OnServerDisconnect(NetworkConnection conn) {
        NetworkServer.DestroyPlayersForConnection(conn);
        if (conn.lastError != NetworkError.Ok) {
            if (LogFilter.logError) { Debug.LogError("ServerDisconnected due to error: " + conn.lastError); }
        }
        Debug.Log("A client disconnected from the server: " + conn);
    }
    public override void OnServerReady(NetworkConnection conn) {
        NetworkServer.SetClientReady(conn);
        Debug.Log("Client is set to the ready state (ready to receive state updates): " + conn);
    }
    public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId) {
        var player = (GameObject)GameObject.Instantiate(playerPrefab, Vector3.zero, Quaternion.identity);
        NetworkServer.AddPlayerForConnection(conn, player, playerControllerId);
        Debug.Log("Client has requested to get his player added to the game");
    }

    public override void OnServerRemovePlayer(NetworkConnection conn, PlayerController player) {
        if (player.gameObject != null)
            NetworkServer.Destroy(player.gameObject);
    }

    public override void OnServerError(NetworkConnection conn, int errorCode) {
        Debug.Log("Server network error occurred: " + (NetworkError)errorCode);
    }

    public override void OnStartHost() {
        Debug.Log("Host has started");
    }

    public override void OnStartServer() {
        Debug.Log("Server has started");
    }

    public override void OnStopServer() {
        Debug.Log("Server has stopped");
    }

    public override void OnStopHost() {
        Debug.Log("Host has stopped");
    }

    // 客户端回调
    public override void OnClientConnect(NetworkConnection conn)
    {
        base.OnClientConnect(conn);
        Debug.Log("Connected successfully to server, now to set up other stuff for the client...");
    }

    public override void OnClientDisconnect(NetworkConnection conn) {
        StopClient();
        if (conn.lastError != NetworkError.Ok)
        {
            if (LogFilter.logError) { Debug.LogError("ClientDisconnected due to error: " + conn.lastError); }
        }
        Debug.Log("Client disconnected from server: " + conn);
    }

    public override void OnClientError(NetworkConnection conn, int errorCode) {
        Debug.Log("Client network error occurred: " + (NetworkError)errorCode);
    }

    public override void OnClientNotReady(NetworkConnection conn) {
        Debug.Log("Server has set client to be not-ready (stop getting state updates)");
    }

    public override void OnStartClient(NetworkClient client) {
        Debug.Log("Client has started");
    }

    public override void OnStopClient() {
        Debug.Log("Client has stopped");
    }

    public override void OnClientSceneChanged(NetworkConnection conn) {
        base.OnClientSceneChanged(conn);
        Debug.Log("Server triggered scene change and we've done the same, do any extra work here for the client...");
    }
}

NetworkManager Inspector 提供了更改某些连接参数和超时的功能。有些参数未在此处公开,但可以通过代码更改这些参数。 代码如下:

代码语言:javascript
复制
using UnityEngine;
using UnityEngine.Networking;

public class CustomManager : NetworkManager {
    // 尽早设置自定义连接参数,确保不会太晚实施这些参数
    void Start()
    {
        customConfig = true;
        connectionConfig.MaxCombinedReliableMessageCount = 40;
        connectionConfig.MaxCombinedReliableMessageSize = 800;
        connectionConfig.MaxSentMessageQueueSize = 2048;
        connectionConfig.IsAcksLong = true;
        globalConfig.ThreadAwakeTimeout = 1;
    }
}

总结

书接上回,承接下回,一系列的。欲知后事如何,且听下回分解。 本次总结的就是这样的, 有需要会继续增加功能 如能帮助到你,就帮忙点个赞吧,三连更好哦,谢谢 你的点赞就是对博主的支持,有问题记得留言评论哦! 不定时更新Unity开发技巧,觉得有用记得一键三连哦。么么哒!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2026-01-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 一、游戏状态管理
    • 1-1、使用 Network Manager HUD
    • 1-2、使用HUD
  • 二、开始位置
  • 场景管理
  • 自定义
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档