Search Unity

  1. Full schedule for #UniteBerlin is now available! Featuring talks on our roadmap, hands-on labs and much more! Check it out!
    Dismiss Notice
  2. Unity 2018.1 has arrived! Read about it here
    Dismiss Notice
  3. Scriptable Render Pipeline improvements, Texture Mipmap Streaming, and more! Check out what we have in store for you in the 2018.2 Beta.
    Dismiss Notice
  4. ARCore is out of developer preview! Read about it here.
    Dismiss Notice
  5. Magic Leap’s Lumin SDK Technical Preview for Unity lets you get started creating content for Magic Leap One™. Find more information on our blog!
    Dismiss Notice
  6. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

Unity Multiplayer ClientScene.RegisterPrefab(assetId, SpawnDelegate, UnSpawnDelegate) issue

Discussion in 'Multiplayer Networking' started by VergilUa, Mar 29, 2017.

  1. VergilUa

    VergilUa

    Joined:
    Dec 22, 2014
    Posts:
    295
    Hi guys. I'm trying to do an objects pooling (for multiple prefab types) spawned via NetworkServer.Spawn but I'm stuck with this issue.
    ClientScene.prefabs are out of sync when I register prefabs on the server and then try to join with a fresh client.

    So I can't get a prefab via assetId called in SpawnDelegate.

    I've checked ClientScene.prefabs dictionary on client, and can confirm that they do not sync on fresh client join.
    Do I have to sync prefabs (ClientScene.prefabs) manually before I join with the client somehow?
    Or maybe there's a way to load a prefab on a client via assetId (which I doubt exists)?

    Also, I can't just put prefabs on spawnable list in NetworkManager, because it overrides Spawn/UnSpawn delegates.

    Any tips appreciated

    Spawn/UnSpawn delegates snippet:
    Code (CSharp):
    1.  
    2.  
    3. public delegate GameObject SpawnDelegate(Vector3 position, NetworkHash128 assetId);
    4. public delegate void UnSpawnDelegate(GameObject spawned);
    5.  
    6. public void RegisterPrefab(GameObject unitPrefab, NetworkHash128 assetId) {
    7.     ClientScene.RegisterPrefab(unitPrefab, SpawnUnit, UnSpawnUnit);
    8. }
    9.  
    10. private GameObject SpawnUnit(Vector3 position, NetworkHash128 assetid) {
    11.  
    12.     ClientScene.prefabs.TryGetValue(assetid, out prefab);
    13.     if (prefab == null) {
    14.         Debug.LogError("UnitPool:: SpawnUnit() - Unable to retrieve prefab by assetId");
    15.     }
    16.  
    17.     return InstantiateFromUnitPool(prefab, position);
    18. }
    19.  
    20. public void UnSpawnUnit(GameObject spawned) {
    21.     Debug.Log("Unspawning");
    22.     spawned.SetActive(false);
    23. }
    24.  
     
    Last edited: Mar 29, 2017
  2. VergilUa

    VergilUa

    Joined:
    Dec 22, 2014
    Posts:
    295
    I've actually managed to do pooling without any spawn/undelegate.
    For those who interested - just pool everything on server (standard instantiate), spawn if it's a new object and update it on clients via Rpc.
     
  3. gsus725

    gsus725

    Joined:
    Aug 23, 2010
    Posts:
    250
  4. hexagonius

    hexagonius

    Joined:
    Mar 26, 2013
    Posts:
    75
    @VergilUa the way you describe your first attempt is not the way this works. The Server knows which prefab it spawns, because you need to instantiate a version of it and pass it to NetworkServer.Spawn. RegisterPrefab needs to be called on the clients because they are the ones that do NOT know what to spawn when the server sends them just a hash. Furthermore, you don't need to provide your own delegate declarations because they're already provided, otherwise the Method would not exist.

    SideNote: I just recently reported a bug that running this from OnStartClient in a NetworkBehaviour that is in a scene used by the NetworkManager as the online scene, is too late for the registration and will throw an error when running in Host mode or server and client on the same machine. Awake is your best bet.