Search Unity

  1. We're looking for feedback on Unity Starter Kits! Let us know what you’d like.
    Dismiss Notice
  2. Unity 2017.2 beta is now available for download.
    Dismiss Notice
  3. Unity 2017.1 is now released.
    Dismiss Notice
  4. Introducing the Unity Essentials Packs! Find out more.
    Dismiss Notice
  5. Check out all the fixes for 5.6 on the patch releases page.
    Dismiss Notice
  6. Help us improve the editor usability and artist workflows. Join our discussion to provide your feedback.
    Dismiss Notice

Unity Multiplayer Networked object pool example for UNet HLAPI

Discussion in 'Multiplayer Networking' started by seanr, Nov 21, 2015.

  1. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    Attached is an example of networked object pool for UNet. It uses custom spawn handler functions and has object pools on the host and clients.

    Instances of the specified "Prefab" object are created at initialization time, and then used when spawn messages are recieved, so there is no run-time object allocation and destruction.

    upload_2015-11-21_13-53-56.png

    The pooled object are controlled by the server. Example usage in a player script:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Networking;
    3.  
    4. public class PlayerMove : NetworkBehaviour
    5. {
    6.  
    7.     public NetworkSpawnPool bulletPool;
    8.  
    9.     void Start()
    10.     {
    11.         bulletPool = NetworkSpawnPool.GetPoolByName("DynamicPool");
    12.     }
    13.     //public GameObject bulletPrefab;
    14.  
    15.     public override void OnStartLocalPlayer()
    16.     {
    17.         GetComponent<MeshRenderer>().material.color = Color.red;
    18.     }
    19.  
    20.     [Command]
    21.     void CmdFire()
    22.     {
    23.  
    24.         var bullet = bulletPool.ServerCreateFromPool(transform.position - transform.forward, Quaternion.identity);
    25.         if (bullet == null)
    26.             return;
    27.  
    28.         bullet.GetComponent<Rigidbody>().velocity = -transform.forward*4;
    29.      
    30.         // spawn the bullet on the clients
    31.         NetworkServer.Spawn(bullet);
    32.  
    33.         bulletPool.ServerReturnToPool(bullet, 2.0f);
    34.     }
    35.  
    36.     void Update()
    37.     {
    38.         if (!isLocalPlayer)
    39.             return;
    40.  
    41.         var x = Input.GetAxis("Horizontal")*0.1f;
    42.         var z = Input.GetAxis("Vertical")*0.1f;
    43.  
    44.         transform.Translate(x, 0, z);
    45.  
    46.         if (Input.GetKeyDown(KeyCode.Space))
    47.         {
    48.             // Command function is called on the client, but invoked on the server
    49.             CmdFire();
    50.         }
    51.     }
    52. }
    Although by default it works with prefabs, there is a virtual function that can be overridden to construct objects from code, like this below:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Networking;
    3. using System.Collections;
    4.  
    5. public class DynamicBulletPool : NetworkSpawnPool {
    6.    
    7.     protected override GameObject InstantiatePrefab(Vector3 pos, Quaternion rot)
    8.     {
    9.         var go = GameObject.CreatePrimitive(PrimitiveType.Sphere);
    10.         go.transform.localScale = new Vector3(0.2f, 0.2f, 0.2f);
    11.         go.transform.position = pos;
    12.         go.transform.rotation = rot;
    13.         var rb = go.AddComponent<Rigidbody>();
    14.         rb.useGravity = false;
    15.         go.AddComponent<NetworkIdentity>();
    16.         go.AddComponent<NetworkTransform>();
    17.         go.AddComponent<Bullet>();
    18.  
    19.         return go;
    20.     }
    21. }
    Spawning with prefabs uses the assetId from the prefab, but dynamically created assetIds can be used.

    The attached project shows it in use.
     

    Attached Files:

  2. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    19,438
    oh excellent. missed this, thanks!
     
  3. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    632
    Excellent indeed, I shall have a play with this later :)
     
  4. Patico

    Patico

    Joined:
    May 21, 2013
    Posts:
    883
    Thank you!
     
  5. moco2k

    moco2k

    Joined:
    Apr 29, 2015
    Posts:
    245
    Thanks for this. However, I've experienced some issues with the example project. In my first try, I've used local host and 1 client (Unity 5.3) and I got some warnings and error messages on the client after some playing around and firing a lot, see attached screenshot. I think the warnings can be ignored, but what about the error?

    Another situation that causes this error is when a host game is stopped (disconnected) while pooled objects are still issued to be returned. At the point when they actuall return, the server is no longer active. This does not seem to be a big deal by itself, but when a new hosted game is started afterwards, a missing reference exception is thrown. To reproduce, just start host, fire some bullets, stop host, and start again.

    Also, the current implementation does not seem to work with scene transitions out-of-the-box. It would be very nice if you can extend the example so that it also features an offline and online scene use case, as this seems to be more like the common case.
     

    Attached Files:

    Last edited: Dec 13, 2015
  6. seanr

    seanr

    Unity Technologies

    Joined:
    Sep 22, 2014
    Posts:
    669
    looks like I posted the wrong version of this project and now I cant find the latest one.

    From memory the Bullet.cs script should not call bulletPool.ServerReturnToPool() on the client, it should disable the bullet locally, (is "isServer" is not set).

    For scene changes, it seems that putting the pool in the "online" scene works best, instead of having it in the offline scene.
     
  7. Chris-Trueman

    Chris-Trueman

    Joined:
    Oct 10, 2014
    Posts:
    316
    I am having an issue where it doesn't spawn the objects in the scene from the object pool if the objects are already in the scene when a client joins a game in progress, causing an error saying "Pool doesn't contain " + go when the object gets unspawned.
     
  8. justjuank

    justjuank

    Joined:
    May 30, 2013
    Posts:
    5
    Hi guys, thanks to your comments and other threads in the forums I was able to make my own implementation of a networking object pooling system.
    I don't know if my solution is totally valid but it works, check it out:
    http://www.justjuank.com/network-object-pooling-for-unity3d/
    Sorry if this is an old thread, just wanted to share it with you.

    Juan
     
    ThinhHB and moco2k like this.
  9. buzheteng

    buzheteng

    Joined:
    Feb 29, 2016
    Posts:
    4
    thanks for sharing~:rolleyes::rolleyes:
     
  10. noahmilam

    noahmilam

    Joined:
    Mar 4, 2015
    Posts:
    3
    when I try you pooling project. the rigidbody velocity is not applied to the clients side. the bullet spawns but does not move forward. any help would be great