Unet Синхронизация анимации слоя с весом Unity 3D - PullRequest
1 голос
/ 04 марта 2020

В настоящее время я работаю над многопользовательским fps для изучения UNET и Unity. В этом проекте я использую компонент Network Animator для синхронизации c моих анимаций. У меня есть один слой, который управляет нормальными состояниями, такими как ходьба и прыжки, и другой, который просто контролирует верхнюю часть тела для обзора. Этот слой активируется при определении области видимости.

Параметры точная синхронизация, но не вес слоя. Сценарий, управляющий весом слоя, отключается на удаленном проигрывателе, поскольку он является частью того же сценария, который выполняет съемку, и мы не хотим снимать с удаленного проигрывателя. Поэтому я поместил этот код в другой сценарий и сделал Layerweight Syncvar, но все еще безрезультатно.

Это фрагмент, который устанавливает вес и постепенно его возвращает.

    if (isScoped)
    {
        animator.SetLayerWeight(1, 1);
        layerWeight = 1;
    }
    else
    {
        layerWeight = Mathf.Lerp(layerWeight, 0, 0.1f);
        animator.SetLayerWeight(1, layerWeight);
    }

    animator.SetBool("Scoped", isScoped);

как можно Я синхронизирую c переменную, которая обновляется в отключенном скрипте? И какие различные пользовательские атрибуты, такие как [Command] и [ClientRpc], я должен использовать, чтобы это работало? Я прочитал документацию и руководства по UNET, но борюсь с этой относительно простой задачей, так как мне трудно понять разницу этих вызовов.

1 Ответ

0 голосов
/ 06 марта 2020

Как правило, основная проблема с [SyncVar] заключается в том, что они

синхронизируются от сервера к клиентам

поэтому не наоборот!


Тогда

[Command] - это метод, который вызывается любым клиентом , но выполняется только на сервере

[ClientRpc] в некотором роде противоположно, вызывается сервером и затем выполняется все клиенты

так что я бы сделал метод установки для слоя с весом, как

private void SetLayerWeight(float value)
{
    // only player with authority may do so
    if(!isLocalPlayer) return;

    // Tell the server to update the value
    CmdSetLayerWeight(value);
}

[Command]
private void CmdSetLayerWeight(float value)
{
    // Server may now tell it to all clients
    RpcSetLayerWeight(value);
}

[ClientRpc]
private void RpcSetLayerWeight(float value)
{
    // called on all clients including server
    layerweight = value;
    animator.SetLayerWeight(1, layerweight);
}

, и назвал бы его как

if (isScoped)
{
    SetLayerWeight(1);
}
else
{
    SetLayerWeight(Mathf.Lerp(layerWeight, 0, 0.1f));
}

Заметьте, однако, что передача этого между сервером и клиентом приведет к какой-то странной задержке!

Возможно, вам лучше синхронизировать isScoped bool и назначить значение непосредственно на вызывающем клиенте:

private void SetScoped(bool value)
{
    // only player with authority may do so
    if(!isLocalPlayer) return;

    // for yourself already apply the value directly so you don't have
    // to wait until it comes back from the server
    scoped = value;

    // Tell the server to update the value and who you are
    CmdSetLayerWeight(value);
}

// Executed only on the server
[Command]
private void CmdSetLayerWeight(bool value)
{
    // Server may now tell it to all clients
    RpcSetLayerWeight(value);
}

// Executed on all clients
[ClientRpc]
private void RpcSetLayerWeight(bool value)
{
    // called on all clients including server
    // since setting a bool is not expensive it doesn't matter
    // if this is done again also on the client who originally initialized this
    scoped = value;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...