UNET SyncVar на стороне сервера не обновляется

Я пытаюсь использовать SyncVar, но я не совсем понимаю, что я делаю неправильно, если я делаю это неправильно. Вот ситуация:

  1. У меня есть две общедоступные SyncVar: redFunds и blueFunds и две локальные «старые» версии для сравнения.

  2. Я инициирую SyncVar в меню «Пуск» с помощью Cmd_UpdateXxx, это работает

  3. У меня есть две кнопки, по одной для каждой SyncVar

  4. В обновлении я сравниваю SyncVar и oldXxxFunds. Если хит я показываю на сцене

Когда я запускаю код, он отображает правильные числа на сцене на обоих проигрывателях (красный и синий), но это не полностью отражается в редакторе при просмотре «общедоступных» SyncVar. При нажатии красной кнопки это отражается в редакторе только на красном игроке, а не на синем.

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

[SyncVar] public int redFunds;
[SyncVar] public int blueFunds;
public int oldRedFunds;
public int oldBlueFunds;

private void Start () 
{

    if (!isLocalPlayer)
        return;

    Cmd_UpdateRed (10);
    Cmd_UpdateBlue (20);
}

// Button
void btn_Red () 
{
    if (!hasAuthority)
        return;

    Cmd_UpdateRed (10000);
}

void btn_Blue () 
{
    if (!hasAuthority)
        return;

    Cmd_UpdateBlue (20000);
}

[Command]
void Cmd_UpdateRed (int _value) 
{
    redFunds = _value;
}

[Command]
void Cmd_UpdateBlue (int _value) 
{
    blueFunds = _value;
}

void Update () 
{
    if (redFunds != oldRedFunds) 
    {
        txt_RedTotalFunds = GameObject.Find ("txt_RedTotalFunds").GetComponent<Text> ();
        txt_RedTotalFunds.text = "$" + redFunds;
        oldRedFunds = redFunds;
    }

    if (blueFunds != oldBlueFunds) 
    {
        txt_BlueTotalFunds = GameObject.Find ("txt_BlueTotalFunds").GetComponent<Text> ();
        txt_BlueTotalFunds.text = "$" + blueFunds;
        oldBlueFunds = blueFunds;
    }
}

person PeterK    schedule 30.06.2017    source источник
comment
Сколько существует объектов с этим скриптом и кто их владельцы?   -  person Fenixrw    schedule 02.07.2017
comment
@Fenixrw это четыре объекта, игроки, в которых находится этот код.   -  person PeterK    schedule 02.07.2017
comment
Я сделаю некоторые тесты здесь, чтобы увидеть, смогу ли я найти проблему.   -  person Fenixrw    schedule 02.07.2017
comment
Я думаю, что понимаю проблему. Переменные красного и синего средств уникальны для каждого игрока, поэтому, если вы обновите красные средства в красном игроке, они не будут обновлены в синем игроке. Я не знаю, возможно ли это с синхронизаторами (должно быть), но вы можете использовать эти переменные как статические, чтобы они принадлежали классу, а не объекту. Другой способ — использовать объект, принадлежащий серверу, для хранения этой информации. Вы можете создать GameRoomInfo NetworkBehavior для хранения данных игровой комнаты.   -  person Fenixrw    schedule 02.07.2017
comment
Пытался создать статическую SyncVar... не работает. Решение GameRoomInfo может быть лучшим подходом.   -  person Fenixrw    schedule 02.07.2017
comment
Питер, подход GameRoomInfo решил проблему?   -  person Fenixrw    schedule 04.07.2017
comment
Я только что проверил вашу структуру, и она сработала :-)   -  person PeterK    schedule 04.07.2017
comment
Рад, что смог помочь :-)   -  person Fenixrw    schedule 04.07.2017


Ответы (1)


Лучший способ, который я могу придумать, - это использовать GameRoomInfo в качестве сетевого объекта, принадлежащего серверу.

Это можно сделать с помощью 2 простых скриптов следующим образом:

Скрипт GameRoomInfo

using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using System.Collections;

public class GameRoomInfo : NetworkBehaviour
{
    public Text txt_RedTotalFunds;
    public Text txt_BlueTotalFunds;

    public int oldRedFunds = 0;
    public int oldBlueFunds = 0;

    [SyncVar]
    public int redFunds;
    [SyncVar]
    public int blueFunds;

    void Update()
    {
        if (redFunds != oldRedFunds)
        {
            //txt_RedTotalFunds = GameObject.Find("txt_RedTotalFunds").GetComponent<Text>();
            txt_RedTotalFunds.text = "$" + redFunds;
            Debug.Log("Red - $" + redFunds);
            oldRedFunds = redFunds;
        }

        if (blueFunds != oldBlueFunds)
        {
            //txt_BlueTotalFunds = GameObject.Find("txt_BlueTotalFunds").GetComponent<Text>();
            txt_BlueTotalFunds.text = "$" + blueFunds;
            Debug.Log("Blue - $" + blueFunds);
            oldBlueFunds = blueFunds;
        }
    }
}

Скрипт игрока

using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using System.Collections;

public class Player : NetworkBehaviour 
{
    public enum PlayerColor
    { 
        Red, 
        Blue
    };

    //used to update the right variables (Blue player updates blueFunds and Red player updates redFunds)
    [SyncVar]
    PlayerColor playerColor;

    static int colorSelect = 0;

    void Start()
    {
        if(isServer) 
        {
            // the server selects the player color when created
            switch(colorSelect % 2)
            {
                case 0:
                    playerColor = PlayerColor.Red;
                    break;
                case 1:
                    playerColor = PlayerColor.Blue;
                    break;
            }

            colorSelect++;
        }
    }

    void Update()
    {
        if (!isLocalPlayer)
            return;

        if (hasAuthority && Input.GetKeyDown(KeyCode.KeypadPlus))
        {
            Cmd_UpdateAdd(10);
        }
    }

    // Button
    void btn_Update()
    {
        if (!hasAuthority)
            return;

        Cmd_Update(0);
    }

    void btn_Add()
    {
        if (!hasAuthority)
            return;

        Cmd_Update(10);
    }


    [Command]
    public void Cmd_Update(int _value)//The command updates the GameRoomInfo variables according to the player color
    {
        switch (playerColor)
        {
            case PlayerColor.Red:
                FindObjectOfType<GameRoomInfo>().redFunds = _value;
                break;

            case PlayerColor.Blue:
                FindObjectOfType<GameRoomInfo>().blueFunds = _value;
                break;

            default:
                break;
        }
    }

    [Command]
    public void Cmd_UpdateAdd(int _value)
    {
        switch (playerColor)
        {
            case PlayerColor.Red:
                FindObjectOfType<GameRoomInfo>().redFunds += _value;
                break;

            case PlayerColor.Blue:
                FindObjectOfType<GameRoomInfo>().blueFunds += _value;
                break;

            default:
                break;
        }
    }
}

Я внес небольшие изменения, чтобы облегчить тестирование. Не стесняйтесь адаптироваться к вашим потребностям.

person Fenixrw    schedule 02.07.2017
comment
Благодаря @Fenixrw я наконец решил проблему, над которой работал несколько месяцев. Решение, как утверждает Fenixrw: Переменные красного и синего средств уникальны для каждого игрока, поэтому, если вы обновите красные средства в красном игроке, они не будут обновлены в синем игроке. Ты мой герой, БОЛЬШОЙ СПАСИБО :-) - person PeterK; 04.07.2017