Unity Netcode主机调用ServerRpc无法执行的问题排查
问题分析与解决方案
问题根源
主机端调用AddNewPlayer_ServerRpc未执行的核心原因是:PlayersListManager对应的NetworkObject未被服务器正确Spawn,导致其IsServer属性为false,ServerRpc方法无法触发;其次是NetworkList的初始化时机不正确,客户端也会创建实例,可能引发同步问题。
解决步骤
1. 确保PlayersListManager的NetworkObject被服务器Spawn
选中PlayersListManager所在的GameObject,检查NetworkObject组件的Spawn On Start选项是否勾选。如果未勾选,需要在主机启动时手动调用Spawn逻辑(仅在服务器端执行):
private void Start() { if (IsServer) { GetComponent<NetworkObject>().Spawn(); } }
2. 修正NetworkList的初始化时机
将NetworkList的初始化移到OnNetworkSpawn中,且仅在服务器端执行,避免客户端创建无效实例:
public class PlayersListManager : NetworkBehaviour { [SerializeField] RectTransform playersListTransform; [SerializeField] GameObject playerNamePrefab; public NetworkList<FixedString32Bytes> playerUsernamesList; public override void OnNetworkSpawn() { base.OnNetworkSpawn(); if (IsServer) { playerUsernamesList = new NetworkList<FixedString32Bytes>(); playerUsernamesList.OnListChanged += OnPlayersListUpdate; } } [ServerRpc(RequireOwnership = false)] public void AddNewPlayer_ServerRpc(string newUsername) { Debug.Log("AddNewPlayer_ServerRpc"); playerUsernamesList.Add(new FixedString32Bytes(newUsername)); } // ...其他代码 }
3. 延迟调用ServerRpc,确保依赖对象完成初始化
主机端NetworkPlayer的OnNetworkSpawn可能早于PlayersListManager的网络初始化,延迟一帧调用ServerRpc避免时机问题:
public class NetworkPlayer : NetworkBehaviour { [SerializeField] private string _username; //DEBUG ONLY public string Username { get; private set; } private MainMenuInteraction mainMenuInteraction; private PlayersListManager playersListManager; public override void OnNetworkSpawn() { base.OnNetworkSpawn(); mainMenuInteraction = FindObjectOfType<MainMenuInteraction>(); playersListManager = FindObjectOfType<PlayersListManager>(); if (IsLocalPlayer) { Username = mainMenuInteraction.GetUsernameText(); _username = Username; StartCoroutine(DelayedCallServerRpc()); } } private IEnumerator DelayedCallServerRpc() { yield return null; // 等待一帧,确保PlayersListManager完成网络Spawn if (playersListManager != null && playersListManager.IsServer) { playersListManager.AddNewPlayer_ServerRpc(Username); } else { Debug.LogError("无法找到有效的PlayersListManager服务器实例"); } } // ...其他代码 }
4. 验证ServerRpc的执行条件(可选)
在AddNewPlayer_ServerRpc开头添加服务器校验,确保只在服务器端执行:
[ServerRpc(RequireOwnership = false)] public void AddNewPlayer_ServerRpc(string newUsername) { if (!IsServer) { Debug.LogError("AddNewPlayer_ServerRpc只能在服务器端执行"); return; } Debug.Log("AddNewPlayer_ServerRpc"); playerUsernamesList.Add(new FixedString32Bytes(newUsername)); }
内容的提问来源于stack exchange,提问作者Giobar
相关产品推荐
相关产品推荐

