Search Unity

Can i get back network gameobjects?

Discussion in 'Connected Games' started by nemeth.balazs, Oct 22, 2012.

  1. nemeth.balazs

    nemeth.balazs

    Joined:
    Oct 22, 2012
    Posts:
    9
    Sorry for my English!

    I have two scenes. In the "Map" scene I have players (gameobjects with networkView). When I load "City" scene, i don't need them temporaly. When I go back to "Map" scene, can I get players back?

    This isn't work:

    Code (csharp):
    1. // Client send message to server when scene loaded
    2. networkView.RPC("RestoreShips", RPCMode.Server, Network.player);
    3.  
    4. [RPC]
    5. void RestoreShips(NetworkPlayer player)
    6. {
    7.     Debug.Log("Ship.RestoreShips");            
    8.     if(Network.isServer)
    9.     {
    10.         Debug.Log("Server find ships");
    11.         GameObject[] temp = GameObject.FindGameObjectsWithTag("Ship");
    12.        
    13.         NetworkViewID[] networkViewIDs = new NetworkViewID[temp.Length];
    14.         Vector3[] positions = new Vector3[temp.Length];
    15.         Quaternion[] quaternions = new Quaternion[temp.Length];
    16.        
    17.         for(int i = 0; i< temp.Length; i++)
    18.         {
    19.             networkViewIDs[i] = temp[i].networkView.viewID;
    20.             positions[i] = temp[i].transform.position;
    21.             quaternions[i] = temp[i].transform.rotation;
    22.  
    23.         }
    24.            
    25.         Debug.Log("Server have " + networkViewIDs.Length + " ship.");
    26.  
    27.         // Send back viewIDs to client  
    28.         networkView.RPC("InstantiateShips", player, networkViewIDs, positions, quaternions);
    29.     }
    30. }
    31.  
    32. [RPC]          
    33. void InstantiateShips(NetworkViewID[] networkViewIDs, Vector3[] positions, Quaternion[] quaternions)
    34. {
    35.     Debug.Log("Client instantiate all ships" );
    36.  
    37.     foreach(int i = 0; i < networkViewIDs.Length; i++)
    38.     {
    39.         if(!networkViewIDs[i].isMine)
    40.         {
    41.         GameObject ship = Instantiate(playerPrefab, positions[i], quaternions[i]) as GameObject;
    42.         ship.networkView.ViewID = networkViewIDs[i]; /// !!!!!!!!!!!
    43.         }
    44.     }
    45. }
    46.  
    ERROR MESSAGE:
    View ID AllocatedID: 150 not found during lookup. Strange behaviour may occur
    Received state update for view id' AllocatedID: 150' but the NetworkView doesn't exist
     
    Last edited: Oct 22, 2012
  2. appels

    appels

    Joined:
    Jun 25, 2010
    Posts:
    2,685
    Once a new scene is loaded, all existing objects will get destroyed unless you call 'DontDestoyOnLoad' on them.
    But then they will exist in all loaded scenes till you destoy it.
    You will need to recreate them when you need them.
     
  3. nemeth.balazs

    nemeth.balazs

    Joined:
    Oct 22, 2012
    Posts:
    9
    But how can I recreate them after destroy? (recreate with same networkViewID than the original, because they are all other players)
     
  4. appels

    appels

    Joined:
    Jun 25, 2010
    Posts:
    2,685
    You will need to store the data somewhere and then recreate them just like you created them the first time.
     
  5. nemeth.balazs

    nemeth.balazs

    Joined:
    Oct 22, 2012
    Posts:
    9
    First time the other client create it with Network.Instantiate().

    If I use Network.Instantiate again, I create a new one not the original. (Different networkViewID, different owner)

    If I use simple Instantiate, I can't connect it with original instance. I have tried set the same networkViewID (like in first post), but it does't work.
     
  6. appels

    appels

    Joined:
    Jun 25, 2010
    Posts:
    2,685
    In this scenario I would let the server be the owner and just delegate the control to the players.
    So the server always knows which objects belongs to which client/connection.
    You can use the NetworkPlayer object to link clients to objects.
     
  7. nemeth.balazs

    nemeth.balazs

    Joined:
    Oct 22, 2012
    Posts:
    9
    OK, the server own all ship. When I go back to "Map" scene, I need get back them, and that is the original problem, ááá!

    I can describe it in a simple example!!


    Code (csharp):
    1. // The client create an object. This appear in server and client to. Suppose that networkViewID = 1;
    2. GameObject go = Network.Instantiate(prefab, position, rotation);
    3.  
    4. GameObject.Destroy(go); // Now, original go exist only in server!
    5.  
    6. SomeVeryLongFunctionThatDontNeedThatGO();
    7.  
    8. // I want get back original go from server!
    9. Network.Instantiate(prefab, position, rotation); // It's not good, because server has 2 go (the original, and a new one);
    10.  
    11. GameObject go2 = Instantiate(prefab);
    12. go2.networkView.viewID = 1;   // It doesn't work, i can't reconnect this new gameobject to original one.
     
  8. appels

    appels

    Joined:
    Jun 25, 2010
    Posts:
    2,685
    No, for the server to own them, it needs to instantiate all the client objects.
    So if a client want's to spawn, it needs to send an RPC to the server asking it to spawn the object.
    The server then delegates control to the client ( basicly telling the client... this is your object, you can control it )
    But the server owns the objects so when you switch scenes, the server needs to store all the needed data to recreate the objects.
    Then when it's time to rebuild, it will create the objects and assign them to the connections/clients.
    You don't even need to set the viewID's, use a reference so the client knows which object it may control.
     
  9. nemeth.balazs

    nemeth.balazs

    Joined:
    Oct 22, 2012
    Posts:
    9
    Sorry for that, but I can't understand how create the same object!!!

    On client1
    Code (csharp):
    1. // Send RPC to server to create an ship
    2. GameObjet cl1 = spawn.NetworkInstantiatePlayerForMe(Network.player);
    New player appers in client1 and server

    On client2
    Code (csharp):
    1. GameObjet cl2 = spawn.NetworkInstantiatePlayerForMe(Network.player);
    New player appears in client1, client2, and server. All object owner is the server.

    Then I loaded new scene, and all my go destroyed on client2. I need to restore with spawn.

    On client2
    Code (csharp):
    1. spawn.RestoreAllForPlayer(Network.player);
    How can server rebulid origial gameobjects from (reference?) to client scene?
     
  10. nemeth.balazs

    nemeth.balazs

    Joined:
    Oct 22, 2012
    Posts:
    9
    O f*ck!

    The original solution almost good, but RPC parameter must be string, NetworkViewID, etc, but not NetworkViewID array. :)

    Code (csharp):
    1. for(int i = 0; i< temp.Length; i++) {
    2.         // Send back viewID to client  
    3.         networkView.RPC("InstantiateONEShip", player, temp[i].networkView.viewID, temp[i].transform.position, temp[i].transform.rotation);
    4. }
     
  11. appels

    appels

    Joined:
    Jun 25, 2010
    Posts:
    2,685
    I think you got the routine but here is an example :

    Code (csharp):
    1. public class SceneSwitcher : MonoBehaviour
    2. {
    3.  
    4.     List<ObjState> SavedObjects;
    5.  
    6.     struct ObjState
    7.     {
    8.         public NetworkPlayer np;
    9.         public int id;
    10.         public Vector3 pos;
    11.         public Quaternion rot;
    12.     }
    13.  
    14.     public void SwitchScene(string sceneName)
    15.     {
    16.         DontDestroyOnLoad(gameObject);
    17.         SavedObjects = new List<ObjState>();
    18.         GameObject[] gos = GameObject.FindGameObjectsWithTag("Player");
    19.         foreach (GameObject go in gos)
    20.         {
    21.             ObjState os = new ObjState();
    22.             os.id = go.GetComponent<MyScript>().myID;
    23.             os.np = go.GetComponent<MyScript>().LocalPlayer;
    24.             os.pos = go.transform.position;
    25.             os.rot = go.transform.rotation;
    26.             SavedObjects.Add(os);
    27.         }
    28.         networkView.RPC("GotoScene", RPCMode.All, sceneName);
    29.     }
    The struct to store the data needed to restore all the objects. Just populate with what you need.
    Save all in an array.
    Then recreate:
    Code (csharp):
    1. if (Network.isServer)
    2.             {
    3.                 foreach (ObjState obj in SavedObjects)
    4.                 {
    5.                     GameObject go = (GameObject)Network.Instantiate(Resources.Load("Prefabs/PlayerPrefab"), obj.pos, obj.rot, 0);
    6.                     ....
    7.                     go.GetComponent<MyScript>().myID = obj.id;
    8.                 }
     
    Last edited: Oct 22, 2012
  12. nemeth.balazs

    nemeth.balazs

    Joined:
    Oct 22, 2012
    Posts:
    9
    Thanks! But I forgot one important thing. :)

    If clients don't change scene together. Maybe client1 is on "Map" scnene, but client2 is in "City".

    But very thanks for all day help!!!!!!!!
     
  13. appels

    appels

    Joined:
    Jun 25, 2010
    Posts:
    2,685
    This will only work if all clients are in the same scene, Unity's networking wasn't built to work in multiple scenes.
     
  14. nemeth.balazs

    nemeth.balazs

    Joined:
    Oct 22, 2012
    Posts:
    9
    And the last question :)

    Is it better, or if I use networkView.SetScope() :) The ships all DontDestroy, SetScope(false) when enter the city, and true if enter Map scene?!
     
  15. appels

    appels

    Joined:
    Jun 25, 2010
    Posts:
    2,685
    No idea if it's better or not. Test it and you will see.
     
  16. JasmineRice

    JasmineRice

    Joined:
    Nov 1, 2012
    Posts:
    2
    Here what you have to do is store these data somewhere and then restore these data again into your working area.
     
  17. ktina

    ktina

    Joined:
    Dec 12, 2012
    Posts:
    1
    I really don't know how to answer that... I'm kinda having the same problem...:(
     
  18. altair2020

    altair2020

    Joined:
    Mar 6, 2011
    Posts:
    28
    Appels is it possible to have multiple scenes with multiple players running on different scenes?
     
  19. fholm

    fholm

    Joined:
    Aug 20, 2011
    Posts:
    2,031
    No, not really. Im sure you could find a work-around somehow but it was not designed to work like this.
     
  20. appels

    appels

    Joined:
    Jun 25, 2010
    Posts:
    2,685
    You would be better and faster off with some third party lib.
     
  21. altair2020

    altair2020

    Joined:
    Mar 6, 2011
    Posts:
    28
    Can anyone suggest a work around or 3rd party lib ? that would be suitable? should i create a new thread?
     
  22. Ashkan_gc

    Ashkan_gc

    Joined:
    Aug 12, 2009
    Posts:
    903
    You can use UnityPark suite as third party lib and build two servers (one for each scene) and just hand over objects between them easily but in built-in networking you might be able to load both scenes on the server (using a new scene which has both of them in itself) and then do other stuff using some hacking and coding like just changing positions and scope on the server when loading scene in client.
     
  23. altair2020

    altair2020

    Joined:
    Mar 6, 2011
    Posts:
    28
    I dont have the dollars for unitypark.

    I will attempt hacking Unity to instantiate multiple scenes at startup... if anyone can provide me with an example or where to begin i would be much obliged.

    Thanks again.

    John
     
  24. Ashkan_gc

    Ashkan_gc

    Joined:
    Aug 12, 2009
    Posts:
    903
    You should do it without Application.LoadLevel. Just Instantiate a root object which you have all others in children of it as your scene and instantiate multiple ones in multiple y positions to avoid collisions.
    Maybe name your root object as 1, 2, 3, 4 to be able to find them or better put them in a list.

    Cheers