2、环境搭建与初始项目:创建Unity项目、导入Mirror网络库、配置NetworkManager、理解网络组件层级

好,咱们正式开始动手了。

这一章,说白了就是搭地基。地基稳不稳,直接决定你后面盖楼会不会塌。我在带团队做联机项目时,见过太多人一上来就写网络逻辑,结果项目结构一团糟,最后不得不重构。嗯,咱们别走那条弯路。

2.1 创建Unity项目

先创建一个新项目。我个人习惯用 3D Core 模板,因为联机游戏不一定非得是3D,但3D模板的灵活性最高。你想想看,2D项目也能用3D模板,反过来就不行了。

版本建议:Unity 2021.3 LTS 或更高版本。Mirror 对2020 LTS也支持,但我建议用新不用旧。我踩过一个坑——2020 LTS下某个网络组件有奇怪的GC问题,升级到2021就解决了。

项目名称我建议用 MultiplayerGame,位置选个英文路径。为什么?因为Mirror某些底层库对中文路径支持不好,我曾经因为这个折腾了一下午。

2.2 导入Mirror网络库

Mirror的导入方式有两种,我分别说说。

方式一:从Asset Store导入(推荐新手)

  1. 打开 Window → Asset Store
  2. 搜索 "Mirror Networking"
  3. 点击 Import 即可

方式二:从GitHub导入(推荐团队协作)

// 在 Packages/manifest.json 中添加:
"com.mirror-networking.mirror": "https://github.com/vis2k/Mirror.git?path=Assets/Mirror"

我个人更推荐第二种。为什么?因为用Git管理项目时,第一种方式会把Mirror的meta文件搞得很乱。我团队里有个新人用第一种方式导入,结果每次pull代码都要重新导入一次,烦得很。

注意:Mirror依赖 System.Runtime.CompilerServices.Unsafe 包。如果导入后报错,去 Package Manager 安装这个包。我遇到过三次这种问题,都是因为Unity版本升级后自动移除了这个依赖。

2.3 配置NetworkManager

导入完成后,咱们来配置核心组件——NetworkManager。

2.3.1 创建NetworkManager对象

在Hierarchy中创建一个空GameObject,命名为 NetworkManager。然后给它挂上两个组件:

  • NetworkManager(核心管理器)
  • NetworkManagerHUD(调试用UI)

NetworkManagerHUD 是开发阶段的利器。它会在游戏运行时生成一个简单的UI,让你能快速启动Host、Client或Server。但记住,正式发布时一定要移除它——我见过有人把HUD带到生产环境,结果玩家能直接点"Stop Server"把整个房间搞崩。

2.3.2 关键参数配置

参数 推荐值 说明
Network Address localhost 本地测试用,发布时改为服务器IP
Transport KCP Transport Mirror默认的可靠UDP传输
Player Prefab (稍后创建) 玩家对象的预制体
Auto Create Player True 客户端连接后自动生成玩家对象

这里有个细节:Transport 的选择。Mirror支持多种传输方式:

  • KCP:基于UDP,速度快,适合动作游戏
  • TCP:稳定但延迟高,适合回合制
  • WebGL:浏览器专用

我一般默认用KCP。除非项目明确需要WebGL支持,否则别碰TCP——延迟高得让人抓狂。

2.4 理解网络组件层级

这是本章最核心的部分。很多新手搞不清NetworkManager、NetworkIdentity、NetworkBehaviour之间的关系。我画个图帮你理解:

NetworkManager(全局管理者)
  └── 管理所有网络连接
  └── 生成/销毁网络对象

NetworkIdentity(网络身份证)
  └── 挂在每个网络对象上
  └── 分配唯一的NetId
  └── 控制对象的网络可见性

NetworkBehaviour(网络行为)
  └── 继承自MonoBehaviour
  └── 提供 [Command]、[ClientRpc] 等网络方法
  └── 控制同步变量

说白了,这三者的关系就像公司架构:

  • NetworkManager 是CEO,管全局
  • NetworkIdentity 是员工工牌,证明你是谁
  • NetworkBehaviour 是具体岗位职责,决定你能干什么

我见过最典型的错误是什么?有人把NetworkIdentity挂在UI Canvas上。结果客户端一连接,整个UI都同步到所有客户端去了,画面惨不忍睹。记住:只有游戏世界中的对象才需要NetworkIdentity,UI、管理器这类全局对象不需要。

2.5 创建第一个网络预制体

咱们来创建一个简单的玩家预制体,验证配置是否生效。

  1. 在Hierarchy创建一个Cube,命名为 Player
  2. 给它挂上 NetworkIdentity 组件
  3. 勾选 Local Player Authority(让客户端能控制自己的玩家)
  4. 创建一个脚本 PlayerController.cs,继承 NetworkBehaviour
  5. 将Player拖入Project窗口,做成预制体
  6. 把预制体拖到NetworkManager的 Player Prefab 槽中
// PlayerController.cs
using UnityEngine;
using Mirror;

public class PlayerController : NetworkBehaviour
{
    void Update()
    {
        // 只有本地玩家才能控制
        if (!isLocalPlayer) return;

        float moveX = Input.GetAxis("Horizontal");
        float moveZ = Input.GetAxis("Vertical");
        transform.Translate(new Vector3(moveX, 0, moveZ) * Time.deltaTime * 5f);
    }
}
关键点:isLocalPlayer 是NetworkBehaviour提供的属性。它判断当前脚本是否属于本地玩家。没有这个判断,所有客户端都会控制所有玩家对象——那画面太美我不敢看。

2.6 测试网络连接

配置完成后,咱们来测试一下:

  1. 点击Play运行游戏
  2. 点击HUD上的 Host (Server + Client) 按钮
  3. 你应该能看到一个Cube出现在场景中
  4. 按WASD键,Cube应该能移动

如果想测试真正的网络连接:

  • Build一个客户端版本(File → Build Settings)
  • 在编辑器中运行Host
  • 打开客户端版本,点击 Client 连接
  • 两个窗口应该都能看到Cube,且各自控制自己的
小技巧:测试时可以在NetworkManagerHUD上看到连接状态。如果显示 "Connected",说明网络通了。如果卡在 "Connecting...",检查防火墙或杀毒软件——我遇到过好几次360把UDP端口给封了。

2.7 本章小结

到这步,咱们已经完成了:

  • 创建了Unity项目并导入了Mirror
  • 配置了NetworkManager的核心参数
  • 理解了NetworkManager → NetworkIdentity → NetworkBehaviour的层级关系
  • 创建了第一个网络预制体并验证了连接

嗯,地基算是打好了。下一章咱们会深入网络同步的核心——SyncVar和Command/Rpc。到时候你会发现,今天搭的这个架子有多重要。

对了,如果你在配置过程中遇到任何问题,别急着翻文档。先检查一下NetworkManager的Player Prefab有没有拖进去——我敢打赌,80%的"连不上"问题都是因为这个。