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

Unity Netcode ServerRpc仅在客户端执行?销毁对象报错排查

问题分析与解决方案

首先纠正你的误解:TestServerRpc绝对是在服务器端执行的,不是客户端。报错的核心原因是:服务器端对应的PlayerController实例里的spawnedObjectTransform变量根本没被赋值。

为什么会出现这个问题?

  • 当主机(同时是服务器+客户端)按空格时,是在服务器端的PlayerController里执行Instantiate并给spawnedObjectTransform赋值,所以后续调用TestServerRpc时,服务器能拿到这个引用销毁对象。
  • 当客户端按空格时,你是在客户端本地的PlayerController实例里执行Instantiate,然后通过Spawn(true)同步对象到服务器,但服务器端对应的PlayerController实例的spawnedObjectTransform并没有被设置——客户端的Update逻辑只在本地运行,服务器端的PlayerController不会执行客户端的输入代码。
  • 当客户端按Y键调用TestServerRpc,这个Rpc跑到服务器端执行时,服务器端的spawnedObjectTransform是空的,自然会报未实例化的错误。

正确的修改方案

要让服务器端能持有生成对象的引用,同时同步给客户端,推荐让服务器负责生成逻辑,再同步引用到客户端:

public class PlayerController : NetworkBehaviour
{
    public GameObject spawnPrefab;
    private NetworkObject _spawnedObject;

    void Update()
    {
        if (!IsOwner)
            return;

        if (Input.GetKeyDown(KeyCode.Space))
        {
            // 让服务器生成对象
            SpawnObjectServerRpc();
        }

        if (Input.GetKeyDown(KeyCode.Y))
        {
            // 先判断本地引用是否存在,避免无效调用
            if (_spawnedObject != null)
            {
                DestroyObjectServerRpc();
            }
        }
    }

    [ServerRpc(RequireOwnership = false)]
    private void SpawnObjectServerRpc()
    {
        GameObject newObj = Instantiate(spawnPrefab);
        _spawnedObject = newObj.GetComponent<NetworkObject>();
        _spawnedObject.Spawn(true);
        // 把生成的对象同步给所有客户端的PlayerController
        SyncSpawnedObjectClientRpc(_spawnedObject);
    }

    [ClientRpc]
    private void SyncSpawnedObjectClientRpc(NetworkObject obj)
    {
        _spawnedObject = obj;
    }

    [ServerRpc(RequireOwnership = false)]
    private void DestroyObjectServerRpc()
    {
        if (_spawnedObject != null)
        {
            Destroy(_spawnedObject.gameObject);
            _spawnedObject = null;
            // 同步清空客户端的引用
            ClearSpawnedObjectClientRpc();
        }
    }

    [ClientRpc]
    private void ClearSpawnedObjectClientRpc()
    {
        _spawnedObject = null;
    }
}

方案说明

  1. 客户端按空格时,不再本地生成对象,而是调用SpawnObjectServerRpc让服务器负责实例化,确保服务器端的_spawnedObject能拿到引用。
  2. 服务器生成对象后,通过SyncSpawnedObjectClientRpc把对象的NetworkObject同步给所有客户端,让客户端的PlayerController也持有有效引用。
  3. 销毁时,客户端调用DestroyObjectServerRpc,服务器用自己持有的引用销毁对象,再同步清空客户端的引用,避免后续无效调用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 06:47:28