You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity Netcode for Game Objects卡牌列表同步问题咨询

问题分析与解决方案

核心问题根源

你的代码存在两个关键错误:

  1. 公共牌库Deck是普通List<string>,未通过Netcode同步机制实现跨客户端状态同步,导致服务器与客户端、客户端之间的牌库状态完全独立
  2. ClientRpc调用逻辑和参数处理有误,加上本地状态不同步,引发调试信息异常与功能失效

修正后的完整代码

using System.Collections.Generic;
using UnityEngine;
using Unity.Netcode;

public class PlayerNetwork : NetworkBehaviour
{
    // 公共牌库:用NetworkList实现跨客户端同步,仅服务器可修改
    private NetworkList<string> _deck;
    // 玩家手牌:每个玩家独立持有,仅同步给自身和服务器
    private NetworkList<string> _playerCards;

    private void Awake()
    {
        // 初始化NetworkList,指定同步权限(服务器可写,客户端可读)
        _deck = new NetworkList<string>(NetworkListEventSettings.NoEvent);
        _playerCards = new NetworkList<string>(NetworkListEventSettings.NoEvent);
    }

    public override void OnNetworkSpawn()
    {
        base.OnNetworkSpawn();
        // 仅服务器初始化牌库,避免多客户端重复添加卡牌
        if (IsServer)
        {
            _deck.Add("Card1");
            _deck.Add("Card2");
            _deck.Add("Card3");
            _deck.Add("Card4");
            _deck.Add("Card5");
        }
    }

    void Update()
    {
        if (!IsOwner) return;
        if (Input.GetKeyDown(KeyCode.T))
        {
            DrawCardServerRpc();
        }
    }

    [ServerRpc(RequireOwnership = true)]
    private void DrawCardServerRpc()
    {
        if (_deck.Count <= 0) return;
        
        // 服务器从牌库取第一张卡牌
        string drawnCard = _deck[0];
        // 服务器移除牌库卡牌(NetworkList自动同步到所有客户端)
        _deck.RemoveAt(0);
        // 给请求抽牌的玩家发送添加手牌指令
        AddCardToPlayerClientRpc(drawnCard, new ClientRpcParams
        {
            Send = new ClientRpcSendParams
            {
                TargetClientIds = new List<ulong> { OwnerClientId }
            }
        });
        // 服务器打印全局调试信息
        Debug.Log($"服务器:玩家 {OwnerClientId} 抽走卡牌 {drawnCard},剩余牌库数量:{_deck.Count}");
    }

    [ClientRpc]
    private void AddCardToPlayerClientRpc(string card, ClientRpcParams clientRpcParams)
    {
        // 目标客户端添加手牌
        _playerCards.Add(card);
        Debug.Log($"客户端 {OwnerClientId}:获得卡牌 {card},当前手牌数量:{_playerCards.Count}");
    }
}

问题逐一解决说明

问题1:仅操作客户端输出调试信息

  • 原代码中UpdateCardsClientRpc未指定目标,且Deck是本地List,其他客户端的牌库状态与服务器完全不一致,导致调试信息无法正确输出
  • 修正后用NetworkList管理牌库,服务器修改后自动同步所有客户端,所有客户端的牌库状态完全统一;同时服务器在DrawCardServerRpc中打印全局日志,每个客户端在AddCardToPlayerClientRpc中打印自身抽牌日志,多客户端场景下会输出对应数量的调试信息

问题2:打包客户端无法添加手牌

  • 原代码中Deck是本地初始化的,打包客户端与编辑器客户端的牌库状态未同步,服务器与客户端的牌库完全独立,导致抽牌逻辑失效
  • 修正后仅服务器初始化Deck,通过NetworkList自动同步到所有客户端,打包客户端启动后会自动同步服务器的牌库状态;抽牌逻辑依赖服务器权威操作,保证所有客户端(包括打包版)功能一致

内容的提问来源于stack exchange,提问作者Twonk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 07:00:20