3

I have a piece of code that is supposed to generate a random tile map which it does for the server only. I can't figure out how to get it to sync to the players when they join it.How would I sync the prefabs that are instigated to the joining players? They load on one player (the server) but when another player joins they don't show up.

enter image description here

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
public class GenerateLevel : NetworkBehaviour {
public int MapSize = 20;
public GameObject prefab;
public GameObject _LeftW;
public GameObject _RightW;
public GameObject _TopW;
public GameObject _Botw;
public GameObject SpawnLocRed;
public GameObject SpawnLocBlue;

public string map;
public override void OnStartServer()
{
    //base.OnStartServer();
    GetComponent<Renderer>().material.color = Color.blue;

}

void Start()
{
    if (!isServer)
    {
        return;
    }


    for (int c = MapSize / 2; c > -MapSize / 2; c--)
    {

        for (int r = -MapSize / 2; r < MapSize / 2; r++)
        {
            var t = Instantiate(prefab, new Vector3(r, 0, c), 
Quaternion.identity);
            NetworkServer.Spawn(t);
            Debug.Log("Col:" + c + " Row:" + r);

            if (Random.Range(0, 3) == 2)
            {
                t.GetComponent<RAISE>().Run();
                map += 1;
            }
            else
            {
                map += 0;
                if (c < 0 - MapSize / 4 && r > 0 + MapSize / 4)
                {
                   var red= Instantiate(SpawnLocRed, new Vector3(r, 2, c), 
Quaternion.identity);
                }
                if (c > 0 + MapSize / 4 && r < 0 - MapSize / 4)
                {
                   var blue= Instantiate(SpawnLocBlue, new Vector3(r, 2, c), 
Quaternion.identity);

                }
            }

            map += "r";

        }
        map += "c";
    }
    Debug.Log(map);
    if (MapSize % 2 == 0)
    {
        GameObject wt = Instantiate(_TopW, new Vector3(-.5f, 0, -MapSize / 2), Quaternion.identity);
        wt.transform.localScale = new Vector3(MapSize, 5, 1);
        GameObject wb = Instantiate(_Botw, new Vector3(-.5f, 0, MapSize / 2+1), Quaternion.identity);
        wb.transform.localScale = new Vector3(MapSize, 5, 1);
        GameObject wl = Instantiate(_LeftW, new Vector3(-MapSize / 2-1, 0, .5f), Quaternion.identity);
        wl.transform.localScale = new Vector3(1, 5, MapSize+2);


        GameObject wr = Instantiate(_RightW, new Vector3(MapSize / 2, 0, .5f), Quaternion.identity);
        wr.transform.localScale = new Vector3(1, 5, MapSize+2);
    }
    else
    {
        GameObject wt = Instantiate(_TopW, new Vector3(-.5f, 0, -MapSize / 2), Quaternion.identity);
        wt.transform.localScale = new Vector3(MapSize-1, 5, 1);
        GameObject wb = Instantiate(_Botw, new Vector3(-.5f, 0, MapSize / 2 + 1), Quaternion.identity);
        wb.transform.localScale = new Vector3(MapSize-1, 5, 1);


        GameObject wl = Instantiate(_LeftW, new Vector3(-MapSize / 2 - 1, 0, .5f), Quaternion.identity);
        wl.transform.localScale = new Vector3(1, 5, MapSize + 1);


        GameObject wr = Instantiate(_RightW, new Vector3(MapSize / 2, 0, .5f), Quaternion.identity);
        wr.transform.localScale = new Vector3(1, 5, MapSize + 1);
    }
    Debug.Log(MapSize % 2);
}

Here is the updated snippet code

public GameObject[] tiles = new GameObject[1000];
public string map;
public override void OnStartServer()
{
    //base.OnStartServer();
    GetComponent<Renderer>().material.color = Color.blue;

}
public void OnPlayerConnected(NetworkPlayer player)
{
    foreach(GameObject go in tiles)
    {
        NetworkServer.Spawn(go);
    }
}

void Start()
{
    if (!isServer)
    {
        return;
    }
    int temp = 0;

    for (int c = MapSize / 2; c > -MapSize / 2; c--)
    {

        for (int r = -MapSize / 2; r < MapSize / 2; r++)
        {
            var t = Instantiate(prefab, new Vector3(r, 0, c), Quaternion.identity);
            tiles[temp] = t;
            NetworkServer.Spawn(t);
         }
     }
}

After some fiddiling I got the tiles to spawn but they are not syncing ot the characters the henerate tile is running for each client seperatrly.

enter image description here

Ethan Baxter
  • 196
  • 2
  • 14

1 Answers1

3

You can't just use the Instantiate function to make prefabs show on the network. There are other things you must do:

1.You must register the prefab through the NetworkManager component. If there are more than one prefab, you must do this for all of them:

enter image description here

2.Attach NetworkIdentity component to the prefab. Note that if you also want to sync the objects transform, you must attach NetworkTransform to the prefab too.

3.After instantiating the prefab, use NetworkServer.Spawn to also instantiate it on the network too.

For example:

//Instantiate on this device
GameObject red = Instantiate(SpawnLocRed, new Vector3(r, 2, c), 
Quaternion.identity);
//Instantiate it on all clients
NetworkServer.Spawn(red);

Finally, you may want to wrap all the code around inside isLocalPlayer to make sure you only instantiate from the local player.

if (isLocalPlayer)
{
    //Instantiate on this device
    GameObject red = Instantiate(SpawnLocRed, new Vector3(r, 2, c), 
    Quaternion.identity);
    //Instantiate it on all clients
    NetworkServer.Spawn(red);    
}
Programmer
  • 121,791
  • 22
  • 236
  • 328
  • I have it all setup until step 3 but the problem is that the generator is random. How could I get it to run once and then sync it to all the clients? I added some pictures. – Ethan Baxter May 18 '18 at 02:01
  • 1
    The-same thing I mentioned my answer especially **step 3**. Instantiate with `Instantiate` once and store the object in a List. When a new client joins, Loop over those Lists and instantiate them on the client with `NetworkServer.Spawn`. – Programmer May 18 '18 at 02:13
  • No. Use List not array so that you can resize it. If it is server, instantiate with `Instantiate` and add to the List. No `NetworkServer.Spawn`......If it is client, loop over the List and instantiate with each one with `NetworkServer.Spawn(currentListLoop);` – Programmer May 18 '18 at 02:31
  • So something like" public List tiles = new List(); public void OnPlayerConnected(NetworkPlayer player) { foreach(GameObject go in tiles) { Instantiate(go); NetworkServer.Spawn(go); } } with var t = Instantiate(prefab, new Vector3(r, 0, c), Quaternion.identity); tiles.Add(t); in the server only script – Ethan Baxter May 18 '18 at 02:38
  • I added another image to display the desync that it is showing it looks like the maps are generating twice each not syncing with the last. – Ethan Baxter May 18 '18 at 11:25
  • This really sucks, I am not on the computer to do a test. When get to my testing PC and I will see If I can replicate this issue. – Programmer May 18 '18 at 11:26
  • would it help if I linked the full project for you – Ethan Baxter May 18 '18 at 11:29
  • Sure. I use Unity 2017.2. Anything version with the-same or below is fine. Don't bother with any project made with Unity above this version since there will likely be unrelated problems. – Programmer May 18 '18 at 11:31
  • Ok. Will test when I get on my test PC – Programmer May 18 '18 at 12:09