Mirror网络库插件使用6

游戏对象

网络游戏对象

需要在玩家间同步,附加了NetworkIdentity组件的游戏对象。
非网络游戏对象

不需要在玩家间进行同步,没有附加NetworkIdentity组件的游戏对象。

玩家游戏对象

玩家游戏对象属于网络游戏对象。

在每个客户端上,属于该客户端的玩家对象被标记为本地玩家,其余玩家对象为远程副本。

本地玩家标识:isLocalPlayer(NetworkBehaviour上属性)是真。

玩家游戏对象在其他客户端有一个自己的副本对象。

服务器持有所有玩家,负责状态计算和同步。

示例:

服务器有所有客户端的副本;

客户端1有本机角色player1和远程角色player2;

客户端2有本机角色player2和远程角色player1。

自定义角色生成

默认情况下,Mirror的NetworkManager会自动生成Player角色。

这导致一个问题,如果player预制体是一个模型,那么所有客户端的player都是一样的。

自定义角色生成可以解决这个问题。

示例:点击UI,创建不同的player

  1. 新建场景,创建空对象,命名为NetworkManager,添加组件SpawnSampleNetworkManager,NetworkManagerHUD,KcpTransport;
  2. 创建cube,capsule,sphere作为不同的player,分别添加组件NetworkIdentity,移除场景中的player;
  3. 新建空对象,命名为PlayerSelector,添加组件PlayerSelector;
  4. NetworkManager对象设置KcpTransport,角色列表;
  5. PlayerSelector对象引用Networkmanager。

注意:

player预制体可以手动添加到Registered Sapwnable Prefabs列表中;

也可以使用代码动态添加player。

如果没有上述任一操作,客户端不会生成对应的对象。

脚本

SpawnMessage用于传递用户选择的playerIndex

csharp 复制代码
using Mirror;
public struct SpawnMessage : NetworkMessage
{
    public int prefabIndex;
}

SpawnSampleNetworkManager中注册角色预制体列表,注册角色生成逻辑,触发客户端断开事件;

csharp 复制代码
using System;
using Mirror;
using UnityEngine;
public class SpawnSampleNetworkManager : NetworkManager
{
    [Serializable]
    public class SpawnPlayer
    {
        public GameObject playerPrefab;
        public Vector3 spawnPosition;
    }

    [Header("角色列表")]
    public SpawnPlayer[] playerPrefabs;

    public event Action OnClientDisconnectAction;

    public override void Awake()
    {
        base.Awake();
        //玩家预制体加入spawnPrefabs
        for (int i = 0; i < playerPrefabs.Length; i++)
        {
            if (!spawnPrefabs.Contains(playerPrefabs[i].playerPrefab))
                spawnPrefabs.Add(playerPrefabs[i].playerPrefab);
        }
    }

    public override void OnStartServer()
    {
        NetworkServer.RegisterHandler<SpawnMessage>(OnSpawnMessage);
    }

    private void OnSpawnMessage(NetworkConnectionToClient client, SpawnMessage message)
    {
        if (message.prefabIndex < 0 || message.prefabIndex >= playerPrefabs.Length)
        {
            Debug.LogError($"Invalid prefab index {message.prefabIndex}");
            return;
        }
        SpawnPlayer spwanPlayer = playerPrefabs[message.prefabIndex];
        GameObject player = Instantiate(spwanPlayer.playerPrefab, spwanPlayer.spawnPosition, Quaternion.identity);
        NetworkServer.AddPlayerForConnection(client, player);
    }

    public override void OnStopServer()
    {
        NetworkServer.UnregisterHandler<SpawnMessage>();
    }

    public override void OnClientDisconnect()
    {
        OnClientDisconnectAction?.Invoke();
    }
}

PlayerSelector使用OnGUI绘制UI,用户点击UI创建不同的player,客户端断开连接重置选择。

csharp 复制代码
using System;
using Mirror;
using UnityEngine;

[Serializable]
public class PlayerSelector : MonoBehaviour
{
    [SerializeField] SpawnSampleNetworkManager manager;

    private bool hasSelectedPlayer = false;
    public Vector2 offest;

    void OnEnable()
    {
        manager.OnClientDisconnectAction += OnClientDisconnected;
    }

    void OnDisable()
    {
        manager.OnClientDisconnectAction -= OnClientDisconnected;
    }

    private void OnClientDisconnected()
    {
        hasSelectedPlayer = false;
    }

    private void OnGUI()
    {
        if (hasSelectedPlayer == false && NetworkClient.isConnected)
        {
            GUILayout.BeginArea(new Rect(offest.x, offest.y, 100f, Screen.height));
            if (GUILayout.Button("选择角色1"))
                SendMessageToServer(0);
            if (GUILayout.Button("选择角色2"))
                SendMessageToServer(1);
            if (GUILayout.Button("选择角色3"))
                SendMessageToServer(2);
            GUILayout.EndArea();
        }
    }

    private void SendMessageToServer(int index)
    {
        if (hasSelectedPlayer == true)
            return;
        SpawnMessage message = new SpawnMessage
        {
            prefabIndex = index
        };
        NetworkClient.Send(message);
        hasSelectedPlayer = true;
    }
}
相关推荐
木梯子2 小时前
深耕商业表达与 IP 打造,卢中伟导师:以表达赋能创始人成长
服务器·网络·tcp/ip
科技块儿2 小时前
IPv4与IPv6在IP地理定位中的技术差异解析
网络·网络协议·tcp/ip
天远Date Lab2 小时前
天远入职背调报告API对接实战:Python构建自动化背景调查中台
大数据·网络·python·自动化
M158227690552 小时前
SG-EIP-TCP-210 EtherNet/IP 转 ModbusTCP 网关 —— 工业异构网络互联的全能桥梁
网络·tcp/ip·php
电子科技圈2 小时前
SmartDV首次以“全栈IP解决方案提供商”身份亮相Embedded World 2026
服务器·网络·人工智能
深念Y2 小时前
OpenWrt路由器通过USB共享网络(随身WiFi/手机)简明教程
网络·智能手机·路由器·openwrt·数码·网络共享·流量
GOATLong2 小时前
TCP&&UDP&&面向字节流&&面向数据报&&报文的理解&&大小端
网络·tcp/ip·udp
茶乡浪子2 小时前
Community Filter应用实战
网络·智能路由器
松果1773 小时前
常见网络攻击技术方法
网络·网络攻击