告别枯燥理论!用Mirror+Unity快速实现一个多人同步小游戏(从预制体注册到Spawn实战)
2026/6/1 3:46:02 网站建设 项目流程

用Mirror+Unity快速打造多人同步方块对战游戏

第一次接触网络同步功能的Unity开发者,往往会被各种理论概念和复杂架构吓退。Mirror框架的出现,让多人游戏开发变得前所未有的简单——今天我们就用30分钟,从零开始实现一个可运行的多人同步方块对战Demo。不需要预先理解所有网络原理,跟着做就能看到实时同步效果!

1. 环境准备与Mirror安装

在Unity Hub中创建全新的3D项目(建议命名为"MirrorCubeDemo"),确保使用较新的Unity版本(2021 LTS或更高)。打开项目后,通过Package Manager安装Mirror:

  1. 菜单栏选择Window > Package Manager
  2. 点击左上角"+"选择Add package from git URL
  3. 输入Mirror的Git地址:https://github.com/vis2k/Mirror.git#upm
  4. 等待安装完成后,检查已安装包列表确认Mirror版本

提示:若遇到安装错误,可尝试先安装依赖项com.unity.nuget.newtonsoft-json

安装完成后,Assets目录下会出现Mirror文件夹。为快速验证安装成功,可以:

// 在任意脚本中添加测试代码 using Mirror; Debug.Log($"Mirror版本: {Mirror.Version}");

2. 创建基础网络架构

在场景中右键创建空对象命名为"NetworkManager",为其添加两个关键组件:

  • Network Manager:核心管理组件
  • KCP Transport:推荐的高效传输协议

调整NetworkManager配置参数:

// 推荐设置(可在Inspector中修改) maxConnections = 4; // 最大玩家数 playerPrefab = Resources.Load<GameObject>("PlayerCube"); // 稍后创建

创建简单的地面平面(Plane)并添加网格碰撞器,这将作为我们的对战舞台。设置位置为(0,0,0),缩放为(5,1,5)形成足够大的区域。

3. 制作可同步的玩家方块

在Prefabs文件夹创建新预制体"PlayerCube",为其添加以下组件:

  1. Network Identity(必需):标记为网络对象
  2. Network Transform:自动同步位置/旋转
  3. Box Collider:添加物理碰撞
  4. Rigidbody:启用重力效果

为立方体创建简单材质并设置鲜艳颜色(如红色),便于区分玩家。关键配置参数:

组件关键参数推荐值
NetworkTransformsyncInterval0.1
RigidbodyisKinematicfalse
BoxCollidersize(1,1,1)

回到NetworkManager,将PlayerCube拖入Registered Spawnable Prefabs列表,或点击Populate按钮自动注册所有带NetworkIdentity的预制体。

注意:Populate可能遗漏某些预制体,建议手动检查确认

4. 实现玩家移动同步逻辑

创建新C#脚本"PlayerController"并继承NetworkBehaviour:

using Mirror; using UnityEngine; public class PlayerController : NetworkBehaviour { [SerializeField] float moveSpeed = 8f; Rigidbody rb; void Start() { rb = GetComponent<Rigidbody>(); if (isLocalPlayer) { Camera.main.transform.SetParent(transform); Camera.main.transform.localPosition = new Vector3(0, 3, -5); } } void Update() { if (!isLocalPlayer) return; float h = Input.GetAxis("Horizontal"); float v = Input.GetAxis("Vertical"); Vector3 move = new Vector3(h, 0, v) * moveSpeed; rb.velocity = move; } }

将此脚本附加到PlayerCube预制体上。代码关键点解析:

  • isLocalPlayer判断确保只控制自己的角色
  • 摄像机跟随逻辑让每个玩家有自己的视角
  • Rigidbody物理移动比直接修改Transform更真实

5. 添加简单对战功能

让我们扩展功能,使方块可以"攻击"其他玩家——被撞击的玩家会被弹飞。修改PlayerController脚本:

[ServerCallback] void OnCollisionEnter(Collision other) { if (other.gameObject.CompareTag("Player")) { Vector3 force = (other.transform.position - transform.position).normalized * 15f; other.gameObject.GetComponent<Rigidbody>().AddForce(force, ForceMode.Impulse); } } [Command] public void CmdChangeColor(Color newColor) { RpcUpdateColor(newColor); } [ClientRpc] void RpcUpdateColor(Color newColor) { GetComponent<Renderer>().material.color = newColor; }

在Update方法中添加颜色切换测试:

if (Input.GetKeyDown(KeyCode.Space)) { CmdChangeColor(Random.ColorHSV()); }

6. 运行与测试技巧

点击Play按钮前,在NetworkManager组件选择运行模式:

  • Host模式:同时作为服务器和客户端(适合本地测试)
  • Client模式:连接到指定服务器
  • Server模式:仅作为服务器运行

测试多人效果的最佳实践:

  1. 菜单栏选择File > Build Settings
  2. 添加当前场景,勾选"Development Build"
  3. 点击"Build And Run"创建独立客户端
  4. 原编辑器窗口以Host模式运行
  5. 观察两个窗口中的方块同步情况

调试网络问题时,可以启用Mirror的详细日志:

// 在初始化代码中添加 Debug.unityLogger.logEnabled = true; NetworkManager.singleton.logLevel = LogLevel.Verbose;

7. 常见问题解决方案

预制体未同步问题

  • 确认所有客户端都有相同预制体
  • 检查NetworkManager中的注册列表
  • 确保预制体有唯一的NetworkIdentity

移动延迟明显

  • 降低NetworkTransform的syncInterval
  • 尝试不同的Transport组件
  • 检查物理模拟时间步长(Time.fixedDeltaTime)

命令/RPC不执行

  • 方法命名必须以Cmd/Rpc开头
  • 参数必须是Mirror支持的基本类型
  • 确保在正确的作用域调用(如Cmd只能在客户端调用)

在项目根目录创建NetworkManager.asset文件保存常用配置,方便团队共享设置。对于更复杂的游戏,建议采用场景网络加载:

// 在NetworkManager中设置 onlineScene = "GameScene"; offlineScene = "LobbyScene";

8. 性能优化进阶技巧

当玩家数量增加时,需要优化网络流量:

  1. 优先级系统
[SyncVar(hook = nameof(UpdatePriority))] int priority = 0; void UpdatePriority(int oldVal, int newVal) { GetComponent<NetworkProximityChecker>().visRange = newVal; }
  1. 视野范围控制
// 添加NetworkProximityChecker组件 checkInterval = 1.0f; visRange = 10f;
  1. 数据压缩
[SyncVar] [SerializeField] [Range(0, 63)] int compressedHealth;
  1. 预测与插值
// NetworkTransform组件中 interpolatePosition = true; interpolateRotation = true;

对于移动同步,可以改用自定义的NetworkTransform脚本:

[SyncVar] Vector3 syncedPosition; void FixedUpdate() { if (isServer) { syncedPosition = transform.position; } else { transform.position = Vector3.Lerp(transform.position, syncedPosition, 0.2f); } }

9. 扩展游戏功能思路

基于当前Demo,可以轻松扩展更多玩法:

  • 得分系统:添加SyncVar记录玩家得分
  • 特殊能力:使用RPC实现全屏特效
  • 物品生成:用NetworkServer.Spawn实例化道具
  • 房间系统:继承NetworkRoomManager创建大厅

例如实现简单的得分系统:

[SyncVar] int playerScore = 0; [ServerCallback] void OnTriggerEnter(Collider other) { if (other.CompareTag("Coin")) { playerScore++; NetworkServer.Destroy(other.gameObject); } }

创建可同步的硬币预制体:

  1. 新建Sphere并添加NetworkIdentity
  2. 添加以下脚本:
public class Coin : NetworkBehaviour { [ServerCallback] void Start() { Invoke(nameof(Respawn), 10f); } [Server] void Respawn() { transform.position = new Vector3(Random.Range(-10,10), 0.5f, Random.Range(-10,10)); gameObject.SetActive(true); } }

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询