Клиент UNET не может отправлять команды серверу, хост может

Итак, как следует из названия, у меня проблема, когда команды, отправляемые клиентом, не запускаются.

Основная функциональность, которую я пытаюсь заставить работать, заключается в том, что когда враг находится перед игроком и я нажимаю, этот игрок будет на мгновение оглушен. Отлично работает, если я хост, и обе стороны прекрасно регистрируются.

Если я играю как клиент, я дохожу до момента, когда команда «должна» быть отправлена, но я замечаю, что получаю предупреждение, в котором говорится: «Попытка отправить команду для нелокального игрока». Кроме того, ничего не происходит на обоих концах. Очевидно, я должен делать что-то неправильное на стороне клиента, но понятия не имею, как это сделать.

Код «проблемы».

            if (Input.GetButtonDown("Fire1")) {
            Ray ray = new Ray(transform.position, transform.forward);
            RaycastHit hit = new RaycastHit();
            Physics.Raycast(ray, out hit, 20f);
            if (hit.transform != null) {
                if (hit.rigidbody != null) {
                    PlayerController controller = hit.rigidbody.GetComponent<PlayerController>();
                    if (controller != null) {
                        if (!controller.stunned) {
                            // Send the stun command to the server
                            controller.CmdStun();
                        }
                    }
                }
            }
        }

Метод вызывает

[Command]
public void CmdStun() {
    // Report that the stun was sent
    UnityEngine.Debug.Log("Stun Sent");
    RpcStun();
}

[ClientRpc]
public void RpcStun() {
    // Activate the stun timer.
    stunTimer.Start();
    // Track the players original color.
    normalColor = manager.color;
    // Make the players bot look like its shut down.
    manager.InitiateColorChange(Color.black);
    // Other code will check against this before trying to send another stun command.
    stunned = true;
}

Редактировать: По запросу здесь два сценария целиком.

http://pastebin.com/mr4A9ZgH

http://pastebin.com/Qg0AjCCD

Конфигурация игрока в единстве:

https://gyazo.com/400c5b3a95c1a58f9b6e930b0c3c853b

https://gyazo.com/c17a7317767a00e2150ff34b03a03e8f

https://gyazo.com/322731aefbe69f9567d2b395523b8f2a

Полное предупреждающее сообщение

Попытка отправить команду не локальному игроку. UnityEngine.Networking.NetworkBehaviour:SendCommandInternal(NetworkWriter, Int32, String) PlayerController:CallCmdStun() ObjectInteractor:Update() (в Assets/Scripts/ObjectInteractor.cs:58)


person Sebastian Thomas Edward Lawe    schedule 03.09.2015    source источник
comment
Итак, играя в качестве удаленного клиента, вы не видите Stun Sent в консоли?   -  person user3071284    schedule 03.09.2015
comment
Если хост отправляет команду, и хост, и клиент получают журнал. Если клиент отправляет команду, на обоих концах ничего не происходит.   -  person Sebastian Thomas Edward Lawe    schedule 04.09.2015
comment
Можно ли подробнее написать о вашей настройке? Поскольку многие необходимые части UNET разбросаны по игровым объектам и коду, устранение неполадок может быть затруднено без полной картины.   -  person user3071284    schedule 04.09.2015
comment
Добавлено несколько ссылок pastebin с полными классами.   -  person Sebastian Thomas Edward Lawe    schedule 04.09.2015
comment
Есть ли другие экземпляры команд, которые не работают с удаленного клиента? Вы проверили, введен ли идентификатор облачного проекта в настройки Unity?   -  person user3071284    schedule 04.09.2015
comment
Я использую локальный хост. В настоящее время это первая команда, которую я пытаюсь заставить работать.   -  person Sebastian Thomas Edward Lawe    schedule 04.09.2015
comment
Я отредактировал свой ответ. Попробуйте зарегистрировать свой проект в Unity на странице multiplayer.unity3d.com, а затем введите идентификатор облачного проекта в поле Unity. настройки.   -  person user3071284    schedule 04.09.2015
comment
Это заставило функцию онлайн-сватовства работать, хотя проблема осталась той же.   -  person Sebastian Thomas Edward Lawe    schedule 04.09.2015
comment
Вы используете последнюю версию патча? У UNET была своя доля ошибок (и исправлений).   -  person user3071284    schedule 04.09.2015
comment
Я использую Unity 5.1.1f1.   -  person Sebastian Thomas Edward Lawe    schedule 04.09.2015
comment
Всегда выполняйте обновление до последнего исправления при работе с UNET. unity3d.com/unity/qa/patch-releases   -  person user3071284    schedule 04.09.2015
comment
Обновился до последнего патча. К сожалению, проблема все еще существует.   -  person Sebastian Thomas Edward Lawe    schedule 04.09.2015
comment
Давайте продолжим обсуждение в чате.   -  person user3071284    schedule 04.09.2015


Ответы (4)


Я предполагаю, что вы вызываете команду на gameobject, который вы порождаете networkserver, или объект уже существует на сцене. В любом случае, объект не является playerprefab, который вы присваиваете ему в NetworkManager's SpawnInfo.

Итак, для тех Объектов, которые 'Trying to send command for non-local player'. Вам нужно дать их NetworkIdentity 'Authority', которые позволят им звонить [Command]. И чтобы дать им «Полномочия», вы должны использовать

NetworkIdentity.AssignClientAuthority(connectionToClient).

И на самом деле NetworkIdentity.AssignClientAuthority может звонить только на сервер. Вам нужен другой [Command] с 'Player' по 'AssignClientAuthority'.

Подробнее здесь:

Unity UNET - вызов [Command] вне объекта игрока

(Я китаец, поэтому, возможно, я не совсем ясно выразился, надеюсь, вы понимаете.)

person 马佳伟    schedule 02.06.2016

Вы должны назначить сценарий корню ОБЪЕКТА. У меня была такая же проблема. Есть несколько ограничений, которые вы должны учитывать.

  1. NetworkIdentity должен находиться в корневом игровом объекте создаваемого префаба.
  2. Сценарии NetworkBehaviour должны находиться в том же игровом объекте, что и NetworkIdentity, а не в дочерних игровых объектах.
  3. Префабы не могут быть зарегистрированы в NetworkManager, если они не имеют NetworkIdentity в своем корневом объекте.
person tarun khatri    schedule 22.07.2016

Убедитесь, что у вас есть компонент NetworkIdentity с установленным флажком Local Player Authority на префабе вашего плеера. Затем над кодом проблемы запустите его, только если это локальный проигрыватель, добавив следующее:

if (!isLocalPlayer)
    return;

РЕДАКТИРОВАНИЕ: обязательно укажите UPID (полученный при регистрации вашего проекта на https://multiplayer.unity3d.com) в настройках проигрывателя Unity («Правка» -> «Настройки проекта» -> «Проигрыватель») в поле «Идентификатор облачного проекта», если вы тестируете удаленные клиенты. Даже если вы используете локальный хост, удаленный клиент использует сервер ретрансляции Unity для подключения к вашей основной игре.

РЕДАКТИРОВАНИЕ 2. Попробуйте изменить вызов с controller.CmdStun() на controller.Stun(). Затем в PlayerController добавьте общедоступную функцию Stun(), которая вызывает частную функцию CmdStun().

person user3071284    schedule 03.09.2015
comment
Я должен был упомянуть, что эта проверка уже происходит до этого блока кода. Кроме того, все уже правильно настроено. Проблема в том, что мой код работает от хоста к клиенту, но не от клиента к хосту по какой-то причине. - person Sebastian Thomas Edward Lawe; 03.09.2015

Как ты сказал:

предупреждение, которое говорит: «Попытка отправить команду для нелокального игрока».

Вы можете отправлять команды из неигровых объектов, как указано в в документах Unity:

Команды отправляются от объектов игрока на клиенте объектам игрока на сервере. В целях безопасности Команды могут быть отправлены только с ВАШЕГО объекта игрока, поэтому вы не можете управлять объектами других игроков.

НО

Начиная с версии Unity 5.2, можно отправлять команды из объектов, не являющихся игроками, которые имеют права доступа клиента. Эти объекты должны быть созданы с помощью NetworkServer.SpawnWithClientAuthority или иметь права доступа, установленные с помощью NetworkIdentity.AssignClientAuthority. Команды, отправленные этим объектом, выполняются на экземпляре объекта на сервере, а не на связанном объекте игрока для клиента.

person Muhammad Faizan Khan    schedule 31.03.2017