Multiplayer /Client Side/ Help Request

Hey guys,

so I’ve been working with Unity3D for over an year and what I know best is that the networking is the hardest thing to achieve so far. And I have some questions to those who can and who I am asking to help me … okay, lets say I have a multiplayer script that creates a server and loads a map and also have a client function that polls the host list and connects to the server chosen and also loads the map given by the server. But here is the problem. Every time the client connects it REloads the map, so if the server has changed the position or rotation of any objects after the client connect the map and all the objects included reset their properties. So my question is how to make the client connect to the map given by the server and also see the changes that have been made by the server/players/ already joined the server ? Thanks in advance to anyone who is going to answer me, also I’d be really thankful if you also give me a code example, because that whole networking is literally driving me crazy and also I still don’t get the networkViewIDs, so A little example of syncing the properties of a single object on client connect would be great. Thanks :slight_smile:

Loading a new scene/level should be done client side, this should not affect the server or other clients. If this is the case, then your logic is wrong.

If I understand you right the way I do it is I have the map(game environment) on all units, I run the server on my iMac, so I sometimes start my first player on my iMac making that the server, then I’ll join that game by using

MasterServer.PollHostList()

to find the game then I join it, sometime on a few iPhones.

So lets say I have a weapon box in the scene, on that weapon box I have a NetworkView component added to it so I can keep track of it in the scene, then if a player picks that weapon box up I use some code like

playerNetworkView.RPC("weaponPickedUpGUIText", RPCMode.Others, playersName, weaponPickedUp);

to tell all the OTHER players that this player has just picked up the weapon box, then I’ll destroy it with

Network.Destroy(gameObject);

so it’s removed from the network, so the only things that are going to be interacted with in the network have NetworkView components added to them, and if they are only used for script then I set them to

stateSynchronization to off
observed to none

this will save network traffic, I’m still new to networking so I’m sure there are a lot more people here that could help you more, as for NetworkID’s as a player joins the game they are given a NetworkID starting from 0, 1, 2, ect … I find these very useful for checking arrays holding information on that particular player.

Hope this points you in the right direction because I know how confusing networking can be …

Okay, I see the point of using an RPC but let me show my problem:

  1. I make server using
void Start()
    {
        DontDestroyOnLoad(this);

        if (isServer)
        {
            Network.InitializeServer(32, 26200, !Network.HavePublicAddress());
            MasterServer.RegisterHost("saedas", "paackapunch");
        }
    }
  1. Then when the host is registered and server intialized it request the LoadLevel function to load a level
[RPC]
    void LoadLevel(string level, int levelPrefix)
    {
        lastLevelPrefix = levelPrefix;

        Network.SetLevelPrefix(levelPrefix);
        Application.LoadLevel(level);

       //GameObject[] objs = (GameObject[]) GameObject.FindObjectsOfType(typeof(GameObject));
    }

    void OnMasterServerEvent(MasterServerEvent masterServer)
    {
        if (masterServer == MasterServerEvent.RegistrationSucceeded  Network.isServer)
        {
            networkView.group = 1;
            networkView.RPC("LoadLevel", RPCMode.AllBuffered, "TestLevel1", lastLevelPrefix + 1);
        }

    }
  1. No the server loads a simple Level with only a CUBE /and camera/ object in it.

  2. I do change the position of the cube from Vector3.zero to lets say Vector3(1,1,1) /in the editor of course/
    /By default the position of the cube in scene is set to Vector3.zero/

Now comes the Client Side:

  1. I have made a ‘Refresh’ button which requests the host list and when it’s receive the host list it shows all the available servers as buttons:
void OnGUI()
    {
        if (GUILayout.Button("Refresh"))
        {
            MasterServer.RequestHostList("saedas");
        }

        if (data != null)
        {
            for (int i = 0; i < data.Length; i++)
            {
                if (GUILayout.Button(data[i].gameName))
                {
                    Network.Connect(data[i]);
                }
            }
        }
    }
  1. I click the button which points to that exact server pointed above and the client calls the LoadLevel function also but after connected to the server:
void OnConnectedToServer()
    {
        if (Network.isClient)
            LoadLevel("TestLevel1", lastLevelPrefix + 1);
    }

    [RPC]
    void LoadLevel(string level, int levelPrefix)
    {
        lastLevelPrefix = levelPrefix;

        Network.SetLevelPrefix(levelPrefix);
        Application.LoadLevel(level);

       //GameObject[] objs = (GameObject[]) GameObject.FindObjectsOfType(typeof(GameObject));
    }

Okay let me now explain the problem:

  1. After the scene is loaded on the client side you can notice that the cube on the client side is having a position of Vector3.zero and also right after the client connects to the server the level on the server side also reloads everything and the position of Vector3(1,1,1) is now Vector3.zero

Let me ask for help:

  1. How can I prevent that from happening ?
  2. What to use ?
  3. I tried with this code put on the cube
public Vector3 currentPos;
    public Quaternion currentRot;

    void FixedUpdate()
    {
        if (networkView.isMine)
        {
            currentPos = transform.position;
            currentRot = transform.rotation;
        }
        else
        {
            transform.position = currentPos;
            transform.rotation = currentRot;
        }
    }

    void OnSerializeNetworkView(BitStream stream, NetworkMessageInfo info)
    {
        if (stream.isWriting)
        {
            stream.Serialize(ref currentPos);
            stream.Serialize(ref currentRot);
        }
        else
        {
            stream.Serialize(ref currentPos);
            stream.Serialize(ref currentRot);
        }
    }

But still the same issue …

Guys, I really want to figure this out and any support would be helpfull, also thank you two for these fast answer.
And by the way @appels what do you mean by ‘Loading a new scene/level should be done client side’, isn’t the server one who loads the level/scene on it’s initialization and the clients are the ones who are connecting to the server ?