Unity Netcode:调用其他脚本ServerRPC方法报错,如何修复?
问题:调用NetworkBehaviour的ServerRpc时出现KeyNotFoundException错误
问题场景
我需要在玩家脚本TestUseScript中调用另一个类DashT的ServerRPC方法,代码示例如下:
DashT.cs
using System.Collections; using System.Collections.Generic; using Unity.Netcode; using UnityEngine; public class DashT : NetworkBehaviour { [ServerRpc] public void UseServerRpc() { Debug.Log(1); } }
TestUseScript.cs
using System.Collections; using System.Collections.Generic; using Unity.Netcode; using UnityEngine; public class TestUseScript : NetworkBehaviour { private void Start() { GameObject obj = new GameObject(); obj.name = string.Format("_{0}", typeof(DashT).Name); DashT skill = obj.AddComponent<DashT>(); if (IsOwner) skill.UseServerRpc(); } }
运行后触发如下错误:
KeyNotFoundException: The given key 'DashT' was not present in the dictionary. System.Collections.Generic.Dictionary`2[TKey,TValue].get_Item (TKey key) (at <20deccf348554c238921b06fec015ff8>:0) Unity.Netcode.NetworkBehaviour.__endSendServerRpc (Unity.Netcode.FastBufferWriter& bufferWriter, System.UInt32 rpcMethodId, Unity.Netcode.ServerRpcParams serverRpcParams, Unity.Netcode.RpcDelivery rpcDelivery) (at ./Library/PackageCache/com.unity.netcode.gameobjects@1.8.1/Runtime/Core/NetworkBehaviour.cs:127) DashT.UseServerRpc () (at Assets/Scripts/Skills/DashT.cs:11) TestUseScript.Start () (at Assets/Scripts/Player/TestUseScript.cs:15)
修复方案
错误核心原因是:你动态创建的DashT所在的GameObject没有被正确注册到Netcode网络系统中。所有继承NetworkBehaviour的组件必须依附在带有NetworkObject组件的GameObject上,且该对象需要通过网络同步(要么是场景预先放置的NetworkObject,要么由服务器Spawn生成)。
方案一:通过服务器Spawn独立技能对象
因为客户端没有权限直接生成网络对象,所以需要先请求服务器创建并注册对象,再调用ServerRpc:
using System.Collections; using System.Collections.Generic; using Unity.Netcode; using UnityEngine; public class TestUseScript : NetworkBehaviour { private void Start() { if (IsOwner) { // 客户端向服务器请求创建技能对象 RequestSpawnDashServerRpc(); } } [ServerRpc] private void RequestSpawnDashServerRpc() { // 服务器端创建对象并添加必要组件 GameObject obj = new GameObject(); obj.name = string.Format("_{0}", typeof(DashT).Name); NetworkObject networkObj = obj.AddComponent<NetworkObject>(); DashT skill = obj.AddComponent<DashT>(); // Spawn对象,同步到所有客户端 networkObj.Spawn(); // 服务器端直接调用ServerRpc,或后续由客户端调用 skill.UseServerRpc(); } }
方案二:复用玩家对象的NetworkObject
如果DashT不需要作为独立网络对象,可以直接将其挂载到玩家对象上(玩家对象本身已有NetworkObject),无需额外Spawn:
using System.Collections; using System.Collections.Generic; using Unity.Netcode; using UnityEngine; public class TestUseScript : NetworkBehaviour { private DashT skill; private void Start() { // 将DashT挂载到当前玩家对象上 skill = gameObject.AddComponent<DashT>(); if (IsOwner) { skill.UseServerRpc(); } } }
关键注意事项
- 所有
NetworkBehaviour组件必须依附在带有NetworkObject的GameObject上 - 动态创建的网络对象必须由**服务器调用
Spawn()**完成注册,客户端不能直接Spawn - ServerRpc的调用方必须是拥有对象权限的客户端(通过
IsOwner判断),且目标NetworkBehaviour所在对象必须已完成网络注册
内容的提问来源于stack exchange,提问作者Канал Shoker 2
相关产品推荐
相关产品推荐

