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

Fusion for Unity中OccupiedTransform网络集合同步问题求助

解决方案

问题根源在于你的OccupiedTransform结构体不符合Fusion网络序列化要求:

  1. 未实现Fusion的INetworkStruct接口、未标记[NetworkStruct],无法被网络集合同步;
  2. 直接使用Unity的Transform引用类型,Fusion无法序列化普通Unity对象引用,必须改用Fusion提供的网络引用类型。

修改后的核心代码

// 符合Fusion网络序列化要求的结构体
[Serializable, NetworkStruct]
public struct OccupiedTransform : INetworkStruct
{
    // 用NetworkObjectReference替代Transform,指向Transform所在的网络对象
    public NetworkObjectReference TransformOwner;
    public PlayerRef Occupier;

    // 辅助方法:通过NetworkRunner获取对应的Transform
    public Transform GetTransform(NetworkRunner runner)
    {
        if (TransformOwner.TryGet(runner, out var networkObj))
        {
            return networkObj.transform;
        }
        return null;
    }
}

// 用[Networked]标记网络集合,替代[SerializeField]以实现网络同步
[Networked] private NetworkLinkedList<OccupiedTransform> _occupiedTransformList = new NetworkLinkedList<OccupiedTransform>();

功能实现代码

检查Transform是否被占用

public bool IsTransformOccupied(NetworkRunner runner, Transform targetTransform)
{
    var targetObjRef = NetworkObjectReference.FromNetworkObject(targetTransform.GetComponent<NetworkObject>());
    
    foreach (var entry in _occupiedTransformList)
    {
        if (entry.TransformOwner == targetObjRef && entry.Occupier != default)
        {
            return true;
        }
    }
    return false;
}

为Transform分配玩家

// 注意:需在服务器端调用,或通过RPC请求服务器执行
public void AssignPlayerToTransform(NetworkRunner runner, Transform targetTransform, PlayerRef player)
{
    var targetObjRef = NetworkObjectReference.FromNetworkObject(targetTransform.GetComponent<NetworkObject>());

    // 先检查是否已有该Transform的记录,有则更新玩家,无则新增
    foreach (var entry in _occupiedTransformList)
    {
        if (entry.TransformOwner == targetObjRef)
        {
            var index = _occupiedTransformList.IndexOf(entry);
            _occupiedTransformList[index] = entry with { Occupier = player };
            return;
        }
    }

    _occupiedTransformList.Add(new OccupiedTransform
    {
        TransformOwner = targetObjRef,
        Occupier = player
    });
}

移除Transform的玩家占用

// 注意:需在服务器端调用,或通过RPC请求服务器执行
public void RemovePlayerFromTransform(NetworkRunner runner, Transform targetTransform)
{
    var targetObjRef = NetworkObjectReference.FromNetworkObject(targetTransform.GetComponent<NetworkObject>());

    foreach (var entry in _occupiedTransformList)
    {
        if (entry.TransformOwner == targetObjRef)
        {
            var index = _occupiedTransformList.IndexOf(entry);
            // 可选:移除整条记录,或仅将Occupier设为default表示未占用
            _occupiedTransformList.RemoveAt(index);
            // _occupiedTransformList[index] = entry with { Occupier = default };
            return;
        }
    }
}

关键注意事项

  • 确保目标Transform所在的GameObject已挂载NetworkObject组件,否则无法生成有效的NetworkObjectReference;
  • 网络集合的修改操作必须在服务器端执行,客户端只能读取集合状态。如果需要客户端触发修改,需通过Rpc方法调用服务器逻辑;
  • PlayerRef是Fusion原生支持的序列化类型,无需额外处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:05:01