Search Unity

How to sync registered spawnable prefabs' network hashes between the Client and server

Discussion in 'Multiplayer' started by WormChickenWizard, May 14, 2017.

  1. WormChickenWizard

    WormChickenWizard

    Joined:
    Jun 25, 2014
    Posts:
    18
    I'm currently having an issue with prefabs not spawning on the client when each of my prefabs are added to the registered spawn-able prefabs via scripting immediately on connection. I know they are registered on the client because they show up in the network manager.



    and when the client connects to the server and attempts to spawn in the objects the server spawned in, I get the following error for each and every object. In this scenario(the mission config files which provide the information where to spawn in each and every object and how) there was just one:



    this is the script that goes through and adds the units to the registered spawnable prefabs:
    Code (CSharp):
    1.     public void Start ()
    2.     {
    3.  
    4.         //adds units to registered spawnable prefabs
    5.         GameObject[] units = Resources.LoadAll<GameObject>("Units/");
    6.         foreach (GameObject unit in units)
    7.         {
    8.             FindObjectOfType<NetworkManager>().spawnPrefabs.Add(unit);
    9.         }
    10.     }
    I need to know how do I get the server to sync up the registered prefabs on each and every client when they connect.
     

    Attached Files:

    Last edited: May 15, 2017
  2. WormChickenWizard

    WormChickenWizard

    Joined:
    Jun 25, 2014
    Posts:
    18
  3. Deleted User

    Deleted User

    Guest

    Hey, I've used my little tool for adding prefabs to the NetworkManager, you just simply need to add a name of the folder and it will run LoadAll functions in Editor Mode which will add prefabs to the script and then attach them to Manager, the only cons is that you need to press the button again if you have added a new prefab to the Resources folder.
    Here is how it's looks:



    In order to make it work you need 2 scripts and 1 method.

    Put CustomEditors.cs in your Editor folder:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3. using UnityEditor;
    4.  
    5. public class CustomEditors
    6. {
    7.  
    8.     [CustomEditor(typeof(CustomPrefabsRegisterTool))]
    9.     public class CustomPrefabsRegister : Editor
    10.     {
    11.  
    12.         public override void OnInspectorGUI()
    13.         {
    14.  
    15.             DrawDefaultInspector();
    16.  
    17.             CustomPrefabsRegisterTool myScript = (CustomPrefabsRegisterTool)target;
    18.             EditorUtility.SetDirty(target);
    19.  
    20.             if (GUILayout.Button("Load prefabs"))
    21.             {
    22.                 myScript.RegisterSpawnablePrefabsFromResources();
    23.             }
    24.         }
    25.  
    26.     }
    27.  
    28.  }
    29.  
    30.  
    31. }

    Then simply put CustomPrefabsRegisterTool.cs anywhere you want inside your project folder:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3.  
    4. [System.Serializable]
    5. public class CustomPrefabsRegisterTool : MonoBehaviour {
    6.  
    7.     [Header("Load from Path Setup")]
    8.     public string[] LoadPaths;
    9.     public List<GameObject> LoadedPrefabs = new List<GameObject>();
    10.  
    11.     public void RegisterSpawnablePrefabsFromResources()
    12.     {
    13.  
    14.         LoadedPrefabs.Clear();
    15.  
    16.         foreach (string str in LoadPaths)
    17.         {
    18.  
    19.             GameObject[] objects = Statics.LoadGameObjectsFromResources(str);
    20.  
    21.             foreach (GameObject prefab in objects)
    22.             {
    23.                 LoadedPrefabs.Add(prefab);
    24.             }
    25.  
    26.  
    27.         }
    28.  
    29.  
    30.     }
    31.  
    32. }
    33.  
    Then simply drag & drop CustomPrefabsRegisterTool.cs to your NetworkManager object, then you should see something like this


    You can add LoadPaths strings to the array. For example, if your folder path is Resources/Units/, just write Units - it will load all gameObjects from Units folder, then click Load Prefabs (you don't need to manually add GameObjects to the Loaded prefabs array, the script will do it instead of you)


    After you done with this, you simply need to add a method to your CustomNetworkManager or singleton object.

    Code (CSharp):
    1. /// <summary>
    2.     /// Register spawnable prefabs;
    3.     /// </summary>
    4.     private void RegisterPrefabs()
    5.     {
    6.  
    7.         CustomPrefabsRegisterTool tool = this.GetComponent<CustomPrefabsRegisterTool>();
    8.         if (tool != null)
    9.         {
    10.             foreach (GameObject go in tool.LoadedPrefabs)
    11.             {
    12.                 this.spawnPrefabs.Add(go);
    13.             }
    14.         }
    15.  
    16.     }
    Hope it will help you :)
     
    Hummy91 likes this.
  4. WormChickenWizard

    WormChickenWizard

    Joined:
    Jun 25, 2014
    Posts:
    18
    Although I do appreciate the reply, for what I am needing, this solution won't suffice. I need the prefabs to be added at runtime of the game. Reason being is so people can mod the game by simply "dragging and dropping" a mod into a folder and the game would load it. With the solution you gave me, you would need to modify the game inside the editor and essentially make another game which is not what I am pushing for. The solution would need to be similar to GMOD where you just add your mods to the game's directory and the game just starts up with it loaded. Another thing that would need to be considered is if you connected to a server that is running mod 'a' and the client is running mods 'a' and 'b', the client would need to disable mod 'b' and connect.
     
  5. WormChickenWizard

    WormChickenWizard

    Joined:
    Jun 25, 2014
    Posts:
    18
  6. StefLeGall

    StefLeGall

    Joined:
    Jul 26, 2017
    Posts:
    3
    Hi,

    Did you find a way for doing this ? Im trying to play around with ClientScene.RegisterPrefab ( myPrefab ) but doesnt seems to work.. Or do I use it badly?
     
  7. Hummy91

    Hummy91

    Joined:
    Jun 7, 2017
    Posts:
    67
    I think you didn't include a custom resource loading class for this call 'Statics.LoadGameObjectsFromResources(str);'. Do you mind adding it to your post, I was hoping to make use of this tool :p Thank you.
     
  8. Deleted User

    Deleted User

    Guest

    You could make it as Extension Method.

    Code (CSharp):
    1. public static GameObject[] LoadGameObjectsFromResources(string loadFromPath){
    2.  
    3.         GameObject[] goArray = Resources.LoadAll<GameObject>(loadFromPath);
    4.  
    5.         return goArray;
    6.  
    7.      }
     
  9. orkungo

    orkungo

    Joined:
    May 3, 2014
    Posts:
    62
    I think that is an issue for dynamic loaded prefabs. I have such a situation say, 100 prefabs are prepared and loaded only 20 of them at the runtime with

    Code (CSharp):
    1. spawnPrefabs.Add(prefab)
    then spawned with

    Code (CSharp):
    1. NetworkServer.Spawn(prefab);
    When a new player joins, loaded prefab Ids are shared with message as an array and client also loads them with
    Code (CSharp):
    1. spawnPrefabs.Add(prefab)
    however there is no time to spawn them.. How to solve it any ideas?
     
    Last edited: Dec 19, 2019