Search Unity

  1. Improved Prefab workflow (includes Nested Prefabs!), 2D isometric Tilemap and more! Get the 2018.3 Beta now.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Let us know a bit about your interests, and if you'd like to become more directly involved. Take our survey!
    Dismiss Notice
  4. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice
  5. 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 'Connected Games' started by VergilUa, Mar 29, 2017.

  1. VergilUa

    VergilUa

    Joined:
    Dec 22, 2014
    Posts:
    745
    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.     GameObject prefab;
    12.  
    13.     ClientScene.prefabs.TryGetValue(assetid, out prefab);
    14.     if (prefab == null) {
    15.         Debug.LogError("UnitPool:: SpawnUnit() - Unable to retrieve prefab by assetId");
    16.     }
    17.  
    18.     return InstantiateFromUnitPool(prefab, position);
    19. }
    20.  
    21. public void UnSpawnUnit(GameObject spawned) {
    22.     Debug.Log("Unspawning");
    23.     spawned.SetActive(false);
    24. }
    25.  
     
    Last edited: Mar 29, 2017
  2. VergilUa

    VergilUa

    Joined:
    Dec 22, 2014
    Posts:
    745
    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:
    95
    @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.