1. We've introduced thread tags, search within a thread and similar thread search. Read more here.
    Dismiss Notice
  2. Learn how you'll soon be able to publish your games to China in four simple steps with Xiaomi. Sign up now for early access.
    Dismiss Notice
  3. Get further faster with the Unity Plus Accelerator Pack, free for new Unity Plus subscribers for a limited time. Click here for more details.
    Dismiss Notice
  4. We've released our first Timeline Experimental Preview, our new tool for creating cutscenes and more! To check it out click here.
    Dismiss Notice
  5. Unity 5.5 is now released.
    Dismiss Notice
  6. Check out all the fixes for 5.5 in patch releases 1 & 2.
    Dismiss Notice
  7. Unity 5.6 beta is now available for download.
    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:
    18,520
    oh excellent. missed this, thanks!
     
  3. Munchy2007

    Munchy2007

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

    Patico

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

    moco2k

    Joined:
    Apr 29, 2015
    Posts:
    221
    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:
    301
    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:
    4
    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
     
    moco2k likes this.
  9. buzheteng

    buzheteng

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

    noahmilam

    Joined:
    Mar 4, 2015
    Posts:
    2
    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