跳转至

Unity 6.3 — 网络模块参考

最后验证: 2026-02-13 Knowledge Gap: Unity 6 使用 Netcode for GameObjects(UNet 已弃用)


概述

Unity 6 网络选项:

  • Netcode for GameObjects(推荐):官方 Unity 多人游戏框架
  • Mirror:社区驱动(UNet 的继任者)
  • Photon:第三方服务(PUN2)
  • 自定义:底层套接字

UNet(Legacy):已弃用,请勿使用。


Netcode for GameObjects

安装

  1. Window > Package Manager
  2. 搜索 “Netcode for GameObjects”
  3. 安装 com.unity.netcode.gameobjects

基本设置

NetworkManager

// Add to scene: GameObject > Add Component > NetworkManager

// Or create custom NetworkManager:
using Unity.Netcode;

public class CustomNetworkManager : MonoBehaviour {
    void Start() {
        NetworkManager.Singleton.StartHost(); // Server + client
        // OR
        NetworkManager.Singleton.StartServer(); // Dedicated server
        // OR
        NetworkManager.Singleton.StartClient(); // Client only
    }
}

NetworkObject(网络 GameObjects){#networkobject-networked-gameobjects}

将 GameObject 标记为网络对象

  1. 将 NetworkObject 组件添加到 GameObject
  2. 必须位于预制体的根节点(不能嵌套)
  3. 在 NetworkManager > NetworkPrefabs List 中注册预制体

生成网络对象

using Unity.Netcode;

public class GameManager : NetworkBehaviour {
    public GameObject playerPrefab;

    [ServerRpc(RequireOwnership = false)]
    public void SpawnPlayerServerRpc(ulong clientId) {
        GameObject player = Instantiate(playerPrefab);
        player.GetComponent<NetworkObject>().SpawnAsPlayerObject(clientId);
    }
}

NetworkBehaviour(网络脚本){#networkbehaviour-networked-scripts}

NetworkBehaviour 基类

using Unity.Netcode;

public class Player : NetworkBehaviour {
    // Called when spawned on network
    public override void OnNetworkSpawn() {
        if (IsOwner) {
            // Only run on owner's client
            GetComponent<Camera>().enabled = true;
        }
    }

    void Update() {
        if (!IsOwner) return; // Only owner can control

        // Handle input
        if (Input.GetKey(KeyCode.W)) {
            MoveServerRpc(Vector3.forward);
        }
    }

    [ServerRpc]
    void MoveServerRpc(Vector3 direction) {
        // Runs on server
        transform.position += direction * Time.deltaTime;
    }
}

网络变量(同步状态){#network-variables-synchronized-state}

NetworkVariable

using Unity.Netcode;

public class Player : NetworkBehaviour {
    // ✅ Auto-synced across clients
    private NetworkVariable<int> health = new NetworkVariable<int>(100);

    public override void OnNetworkSpawn() {
        // Subscribe to value changes
        health.OnValueChanged += OnHealthChanged;
    }

    void OnHealthChanged(int oldValue, int newValue) {
        Debug.Log($"Health changed: {oldValue} -> {newValue}");
        UpdateHealthUI(newValue);
    }

    [ServerRpc]
    public void TakeDamageServerRpc(int damage) {
        // Only server can modify NetworkVariable
        health.Value -= damage;
    }
}

NetworkVariable 权限

// Server can write, clients read-only (default)
private NetworkVariable<int> score = new NetworkVariable<int>();

// Owner can write
private NetworkVariable<int> ammo = new NetworkVariable<int>(
    default,
    NetworkVariableReadPermission.Everyone,
    NetworkVariableWritePermission.Owner
);

RPC(远程过程调用){#rpcs-remote-procedure-calls}

ServerRpc(客户端 → 服务器){#serverrpc-client--server}

// Client calls, server executes
[ServerRpc]
void FireWeaponServerRpc() {
    // Runs on server
    Debug.Log("Server: Weapon fired");
}

// Call from client:
if (IsOwner && Input.GetKeyDown(KeyCode.Space)) {
    FireWeaponServerRpc();
}

ClientRpc(服务器 → 所有客户端){#clientrpc-server--all-clients}

// Server calls, all clients execute
[ClientRpc]
void PlayExplosionClientRpc(Vector3 position) {
    // Runs on all clients
    Instantiate(explosionPrefab, position, Quaternion.identity);
}

// Call from server:
[ServerRpc]
void ExplodeServerRpc(Vector3 position) {
    // Server logic
    DealDamageToNearbyPlayers(position);

    // Notify all clients
    PlayExplosionClientRpc(position);
}

RPC 参数

// ✅ Supported: Primitives, structs, strings, arrays
[ServerRpc]
void SetNameServerRpc(string playerName) { }

[ClientRpc]
void UpdateScoresClientRpc(int[] scores) { }

// ❌ Not supported: MonoBehaviour, GameObject (use NetworkObjectReference)

网络所有权

检查所有权

if (IsOwner) {
    // This client owns this NetworkObject
}

if (IsServer) {
    // Running on server
}

if (IsClient) {
    // Running on client
}

if (IsLocalPlayer) {
    // This is the local player object
}

转移所有权

// Server transfers ownership
NetworkObject netObj = GetComponent<NetworkObject>();
netObj.ChangeOwnership(newOwnerClientId);

NetworkObjectReference(在 RPC 中传递 GameObjects){#networkobjectreference-pass-gameobjects-in-rpcs}

using Unity.Netcode;

[ServerRpc]
void AttackTargetServerRpc(NetworkObjectReference targetRef) {
    if (targetRef.TryGet(out NetworkObject target)) {
        // Got the target object
        target.GetComponent<Health>().TakeDamage(10);
    }
}

// Call:
NetworkObject targetNetObj = target.GetComponent<NetworkObject>();
AttackTargetServerRpc(targetNetObj);

客户端-服务器架构

public class Player : NetworkBehaviour {
    private NetworkVariable<Vector3> position = new NetworkVariable<Vector3>();

    void Update() {
        if (IsOwner) {
            // Client: Send input to server
            Vector3 input = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
            MoveServerRpc(input);
        }

        // All clients: Sync to networked position
        transform.position = position.Value;
    }

    [ServerRpc]
    void MoveServerRpc(Vector3 input) {
        // Server: Validate and apply movement
        position.Value += input * Time.deltaTime * moveSpeed;
    }
}

网络传输

Unity Transport(默认)

// Configured in NetworkManager:
// - Transport: Unity Transport
// - Address: 127.0.0.1 (localhost) or server IP
// - Port: 7777 (default)

连接事件

void Start() {
    NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnected;
    NetworkManager.Singleton.OnClientDisconnectCallback += OnClientDisconnected;
}

void OnClientConnected(ulong clientId) {
    Debug.Log($"Client {clientId} connected");
}

void OnClientDisconnected(ulong clientId) {
    Debug.Log($"Client {clientId} disconnected");
}

Performance Tips

减少网络流量

  • 使用 NetworkVariable 处理变化不频繁的状态
  • 在同步前批量合并多次更改
  • 对大型数据使用增量压缩

预测与修正

  • 在本地运行移动逻辑以保证响应性
  • 与服务器权威状态进行同步校正
  • 使用插值实现平滑移动

调试

网络分析器

  • Window > Analysis > Network Profiler
  • 监控带宽、RPC 调用和变量更新

网络模拟器(测试延迟/丢包)

  • NetworkManager > Network Simulator
  • 为测试添加人为延迟和丢包

参考来源

  • https://docs-multiplayer.unity3d.com/netcode/current/about/
  • https://docs-multiplayer.unity3d.com/netcode/current/learn/bossroom/

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 cl/Claude-Code-Game-Studios