1

目标:对象可以被玩家交互,并且它的位置和旋转是同步的(局域网)。

场景设置:类似于镜子中的乒乓示例的简单场景,当两个玩家都生成时,会生成一个立方体,两个玩家可以同步交互。

测试立方体 - 在网络管理器中注册为具有网络身份/网络转换的可生成预制件,并在两个玩家加入时生成,并在按下“z”或“x”时移动它的简单旋转脚本,

public Transform LeftPlayerSpawn;
public Transform RightPlayertSpawn;
GameObject Testcube;

public override void OnServerAddPlayer(NetworkConnection conn)
{
    Transform start = numPlayers == 0 ? LeftPlayerSpawn : RightPlayertSpawn;
    GameObject player = Instantiate(playerPrefab, start.position, start.rotation);
    NetworkServer.AddPlayerForConnection(conn, player);

    if (numPlayers == 2)
    {
        Testcube = Instantiate(spawnPrefabs.Find(prefab => prefab.name == "TestCube"));
        NetworkServer.Spawn(Testcube);
    }
}

问题:服务器中所做的任何更改都会反映在客户端中,本地玩家可以控制对象但不与其他客户端同步。 不同步的视频

问题: Networktransform 组件中的 bool- 客户端权限的目的是什么,它应该在具有权限的客户端移动它时自动同步该特定变换还是允许用户通过脚本手动同步?

来自镜像文档 - “默认情况下,网络转换是服务器权威的,除非您选中客户端权限复选框。客户端权限适用于玩家对象以及专门分配给客户端的非玩家对象,但仅适用于此组件.启用此功能后,位置更改将从客户端发送到服务器“。

还尝试通过附加到测试立方体的 SyncPosRot 脚本通过 [Command]/[CientRpc] 更新位置和旋转,

void Update()
{
    if (isLocalPlayer) 
    {
        CmdSyncPosRot(transform.localPosition, transform.localRotation);
    } 
}

[Command]
void CmdSyncPosRot(Vector3 localPosition, Quaternion localRotation)
{
    RpcSyncPosRot(localPosition, localRotation);
}

[ClientRpc]
void RpcSyncPosRot(Vector3 localPosition, Quaternion localRotation)
{
    if (!isLocalPlayer) 
    {
        transform.localPosition = localPosition;
        transform.localRotation = localRotation;
    }
}

尝试并失败:

  1. 尝试使用和不使用 SyncPosRot 脚本,
  2. 在网络转换组件中尝试使用和不使用 bool- 客户端权限,
  3. 将网络身份/网络转换移动到检查器的顶部和底部,因为这似乎可以解决其他有类似问题的同步问题(不适合我),

以上所有经过多次构建但没有结果,

如果修复很简单,例如从服务器生成对象 - 所有玩家都拥有所有权,任何人都可以指导我吗?

另外,如果有更简单的方法(不一定是更好的方法/最佳实践),请告诉我。

4

2 回答 2

0

生成测试立方体时未添加所有者:

    if (numPlayers == 0)
    {
        player1 = Instantiate(playerPrefab, LeftPlayerSpawn.position, LeftPlayerSpawn.rotation);
        NetworkServer.AddPlayerForConnection(conn, player1);
        spawn1 = true;
    }
    if (numPlayers == 1)
    {
        player2 = Instantiate(playerPrefab, RightPlayertSpawn.position, RightPlayertSpawn.rotation);
        NetworkServer.AddPlayerForConnection(conn, player2);
        spawn2 = true;
    }
    if (spawn1 && spawn2)
    {
        Testcube = Instantiate(spawnPrefabs.Find(prefab => prefab.name == "TestCube"));
        NetworkServer.Spawn(Testcube,player1);
    }

这从 player1 输入同步旋转和位置,但不是 player2。

于 2020-09-23T11:54:12.617 回答
0

尝试这个:

if (isServer)
{
    RpcSyncPosRot(transform.localPosition, transform.localRotation);
}
else
{
    CmdSyncPosRot(transform.localPosition, transform.localRotation);
}
于 2020-09-23T08:04:05.987 回答