Сеть Unity / Mirror без клиентской синхронизации

Цель: объект может взаимодействовать с обоими игроками, его положение и вращение синхронизируются (LAN).

Настройка сцены: простая сцена, похожая на пример понга в зеркале, когда оба игрока порождаются, создается куб, с которым оба игрока могут взаимодействовать с синхронизацией.

Тестовый куб - зарегистрирован как префаб с возможностью создания в диспетчере сети с идентификатором сети / преобразованием сети и порожден, когда оба игрока присоединяются, и простой сценарий вращения, который перемещает его при нажатии 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);
    }
}

Проблема: любое изменение, сделанное на сервере, отражается на клиентах, и локальный игрок контролирует объект, но не синхронизируется с другим клиентом. Видео без синхронизации

Вопрос: Какова цель полномочий bool-client в компоненте Networktransform, должен ли он автоматически синхронизировать это конкретное преобразование, когда клиент с полномочиями перемещает его, или он позволяет пользователю синхронизировать вручную через скрипты?

Из документов зеркала - по умолчанию Network Transform является авторитетным сервером, если вы не установите флажок для Client Authority. Полномочия клиента применяются к объектам игроков, а также к объектам, не относящимся к игрокам, которые были специально назначены клиенту, но только для этого компонента. Если этот параметр включен, изменения позиции отправляются от клиента на сервер.

Также пытался обновить положение и вращение через [Command] / [CientRpc] через скрипт SyncPosRot, прикрепленный к тестовому кубу,

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-client и без них в компоненте преобразования сети,
  3. Перемещение идентификатора сети / преобразования сети в верхнюю и нижнюю часть инспектора, поскольку это, казалось, исправляло синхронизацию для других, у которых была аналогичная проблема (не для меня),

Все вышеперечисленное после нескольких сборок и без результатов,

Если исправление представляет собой нечто простое, например создание объекта с сервера - на котором все игроки владеют, может ли кто-нибудь помочь мне?

Также, если есть более простой способ (не обязательно лучший способ / передовая практика), пожалуйста, дайте мне знать.


person sparkblack    schedule 23.09.2020    source источник


Ответы (2)


Попробуй это:

if (isServer)
{
    RpcSyncPosRot(transform.localPosition, transform.localRotation);
}
else
{
    CmdSyncPosRot(transform.localPosition, transform.localRotation);
}
person Fatih Aslan    schedule 23.09.2020
comment
После использования выше в обновлении SyncPosRot: только сервер может вносить изменения, без клиентского ввода. - person sparkblack; 23.09.2020
comment
Вы написали мой код внутри if(islocalplayer) ?. На видео движение ваших кубиков игрока синхронизировано на сервере. В чем разница с большим кубом? Вы используете какую-нибудь синх-переменную? А также можете удалить if(!islocalplayer) в clientrpc и снова протестировать (я не уверен в этом, но у меня их нет в моем работающем проекте). - person Fatih Aslan; 23.09.2020
comment
Хорошо, не могли бы вы подтвердить, возможно ли создавать объекты, которые могут иметь всех клиентов в качестве владельцев? - person sparkblack; 23.09.2020
comment
Да, это возможно. Напишите мой код внутри if (islocalplayer) внутри обновления - person Fatih Aslan; 23.09.2020
comment
Да, я пробовал это, извините, что не упомянул ранее. Тем не менее, та же проблема. Также пробовал с if (! Islocalplayer) и без него в clientrpc. - person sparkblack; 23.09.2020
comment
осталось два :) 1-В видео движение ваших кубиков игрока синхронизировано на сервере, так в чем разница между кубом игрока и большим кубом? 2-Вы используете какую-нибудь синх-переменную? Бонус. Вы использовали debug.logs, если клиенты отправляют какие-либо данные в вашу командную функцию? - person Fatih Aslan; 23.09.2020
comment
Также я не использую никакую переменную синхронизации, а поскольку у игрока есть сетевое преобразование (не отмечены полномочия клиента NT), а также дочерние компоненты сетевого преобразования и куб в качестве его дочернего элемента (куб, назначенный в целевом поле NTC с проверенными полномочиями клиента), разница возникает метод и куб получает обновление положения / поворота из локальной установки. - person sparkblack; 23.09.2020
comment
Не могли бы вы проверить, правильно ли я создаю тестовый куб? - person sparkblack; 23.09.2020
comment
Используйте SyncVar для переменных куба. И [docs.unity3d.com/Manual/UNetStateSync.html] - person Fatih Aslan; 23.09.2020

Не добавлял владельца при создании тестового куба:

    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.

person sparkblack    schedule 23.09.2020