Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.

How to SetActive() synchronization (PUN)

Discussion in 'Multiplayer' started by Mirvox1114, Oct 9, 2022.

  1. Mirvox1114

    Mirvox1114

    Joined:
    Mar 31, 2022
    Posts:
    6
    Im begginer game dev and trying to synchronize SetActive(). (Im not good at English and codding terms, sorry)

    • There are 2 players in this Scene. Both players can see mesh corresponding to player1deck[0] but when i am trying to SetActive child objects in script bellow players only see thair respective meshes active but not the meshes of second player.

    • Im used PhotonNetwork.Instantiate(player1deck[0].name, new Vector3(0, -4, 0), new Quaternion(0, 180, 0, 0)); in other script.
    • In Start() im getting Array of Items from other scene (i susspect problem can be here), then in ShowMesh() im calling SetActive() to all elements in the array (without i = 0 becouse its already active), but only i can see those meshes. (player1deck[0] is a perent of other meshes)
    Hope You can understand what i was trying to say. Thanks
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Photon.Pun;
    5. using Photon.Realtime;
    6.  
    7. public class DeckCopy : MonoBehaviourPunCallbacks
    8. {
    9.     public Item[] player1deck;
    10.  
    11.     PhotonView view;
    12.  
    13.     Transform itemPerent1;
    14.     string objectName;
    15.  
    16.     public string playerInHierarchy;
    17.  
    18.     void Start()
    19.     {
    20.        
    21.         view = GetComponent<PhotonView>();
    22.         if (view.IsMine)
    23.         {    
    24.             ShowMesh();
    25.             view.RPC("ShowMesh", RpcTarget.OthersBuffered);
    26.         }
    27.        
    28.     }
    29.  
    30.     [PunRPC]
    31.     void ShowMesh()
    32.     {
    33.         player1deck = Deck.instance.TransferDeck(); //Array of Items located in other scene
    34.         playerInHierarchy = player1deck[0].name + "(Clone)";
    35.         itemPerent1 = GameObject.Find(playerInHierarchy).transform;
    36.         for (int i = 1; i < 4; i++)
    37.         {
    38.             objectName = player1deck[i].name;
    39.             itemPerent1.transform.Find(objectName).gameObject.SetActive(true);
    40.         }
    41.     }
    42.  
    43. }
     
  2. Mirvox1114

    Mirvox1114

    Joined:
    Mar 31, 2022
    Posts:
    6
  3. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,716
    I notice you are using Start() to call the ShowMesh RPC. It may not be the cause of the problem, but I would usually use the OnPhotonInstantiate callback instead to do this kind of initialization, as it is more flexible.

    I think however, that the problem is that it looks like you are only invoking the ShowMesh RPC on new clients when they join, which updates the already existing clients with the information from the new player, but clients already in the game aren't sending their own information to newly joining players in return.

    You may be able to solve this using the OnPlayerEnteredRoom callback, by having each client send it's information to the newly joined player.
     
    Mirvox1114 likes this.
  4. Mirvox1114

    Mirvox1114

    Joined:
    Mar 31, 2022
    Posts:
    6
    Thanks You @Munchy2007 , i dont exactly understand it right now but am i moving to right direction?
    (its not working right now but i think i will figure it out)
    Code (CSharp):
    1. public override void OnPlayerEnteredRoom(Player newPlayer)
    2.     {
    3.         if (view.IsMine)
    4.         {
    5.             ShowMesh();
    6.             view.RPC("ShowMesh", RpcTarget.OthersBuffered);
    7.         }
    8.     }
    Also, in description i said "In Start() im getting Array of Items from other scene", but then i changed it in the script and put it in showmesh(), and forgot to change description.

    Also i still didnt make player limit, and players joining game scene all the way from lobby scene so 1 player can join without second one right now, may be this can also be a problem, and i should have started with this first?
     
    Last edited: Oct 9, 2022
  5. Mirvox1114

    Mirvox1114

    Joined:
    Mar 31, 2022
    Posts:
    6
    Can problem also be in this 2 scripts?
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using Photon.Pun;
    6.  
    7. public class CreateAndJoinRooms : MonoBehaviourPunCallbacks
    8. {
    9.     public InputField createInput;
    10.     public InputField joinInput;
    11.  
    12.     public void CreateRoom()
    13.     {
    14.         PhotonNetwork.CreateRoom(createInput.text);
    15.     }
    16.  
    17.     public void JoinRoom()
    18.     {
    19.         PhotonNetwork.JoinRoom(joinInput.text);
    20.     }
    21.     public override void OnJoinedRoom()
    22.     {
    23.         PhotonNetwork.LoadLevel("Game");
    24.     }
    25. }
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Photon.Pun;
    5. using UnityEngine.SceneManagement;
    6.  
    7. public class ConnectToServer : MonoBehaviourPunCallbacks
    8. {
    9.     private void Start()
    10.     {
    11.         PhotonNetwork.ConnectUsingSettings();
    12.     }
    13.  
    14.     public override void OnConnectedToMaster()
    15.     {
    16.         PhotonNetwork.JoinLobby();
    17.     }
    18.     public override void OnJoinedLobby()
    19.     {
    20.         SceneManager.LoadScene("Lobby");
    21.     }
    22. }
    23.  
     
  6. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,716
    If I'm correctly understanding what you're trying to do, you need to make a couple of changes to the OnPlayerEnteredRoom method.

    First of all, you shouldn't need to call the ShowMesh method, as you'll be executing this code on the local client that will already have set itself up (I assume).

    Secondly, you should use the newPlayer argument as the RPCTarget and send the data that is required for the new player to correctly display the state of the client(s) that is(are) responding to the OnPlayerEnteredRoom callback. The RPC function that you invoke needs to use that data to set the state of it's instance of the networked object that invoked the RPC.

    There may be better ways to handle this, but it seems to work okay for me for similar situations.

    I don't think the other two scripts, or the fact that the first player can join the room before others connect are causing the issue.
     
    Last edited: Oct 10, 2022
    Mirvox1114 likes this.
  7. Mirvox1114

    Mirvox1114

    Joined:
    Mar 31, 2022
    Posts:
    6
    Thanks again @Munchy2007, as for right now my script looks like this, and its still do not working
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Photon.Pun;
    5. using Photon.Realtime;
    6.  
    7. public class DeckCopy : MonoBehaviourPunCallbacks
    8. {
    9.  
    10.     public Item[] player1deck;
    11.  
    12.     Animator animator;
    13.  
    14.     PhotonView view;
    15.  
    16.     Transform itemPerent1;
    17.     string objectName;
    18.  
    19.     public string playerInHierarchy;
    20.  
    21.     void Start()
    22.     {
    23.         animator = GetComponent<Animator>();
    24.         animator.SetFloat("animationIndex", 2);
    25.  
    26.         view = GetComponent<PhotonView>();
    27.  
    28.         player1deck = Deck.instance.TransferDeck();
    29.         playerInHierarchy = player1deck[0].name + "(Clone)";
    30.         itemPerent1 = GameObject.Find(playerInHierarchy).transform;
    31.  
    32.         ShowMesh(player1deck, itemPerent1);
    33.  
    34.  
    35.     }
    36.  
    37.     public override void OnPlayerEnteredRoom(Player newPlayer)
    38.     {
    39.         if (view.IsMine)
    40.         {
    41.             view.RPC("ShowMesh", RpcTarget.AllBuffered, player1deck, itemPerent1);
    42.         }
    43.     }
    44.  
    45.     [PunRPC]
    46.     void ShowMesh(Item[] playerdeck, Transform itemPerent)
    47.     {
    48.         for (int i = 1; i < 4; i++)
    49.         {
    50.             objectName = playerdeck[i].name;
    51.             itemPerent.transform.Find(objectName).gameObject.SetActive(true);
    52.         }
    53.     }
    54.  
    55. }
    Also im getting this error
    - "Exception: Write failed. Custom type of element not found: Item"
    As i understude its becouse i cant put custom array type in her "view.RPC("ShowMesh", RpcTarget.AllBuffered, player1deck, itemPerent1);"

    Do you know how to fix it?

    Also i dont exactly understand how will first player get info about second one.
     
  8. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,716
    That is correct, you need to work out a way to encode your array into something that PUN can serialize. Probably the easiest solution (if not the most efficient in terms of network traffic) is to convert it to a JSON string and send that, then, on the receiving client, recreate the array from the string and do what you want with it.

    Alternatively you could implement a custom serializer for your item array Serialization in Photon | Photon Engine

    My preferred method is to use custom instantiation data Instantiation | Photon Engine to set the initial state of all networked objects as they join. I would do this in the OnPhotonInstantiate callback on all clients (do not do a photonView.IsMine check for this part).
     
    Last edited: Oct 11, 2022
    tobiass and Mirvox1114 like this.
  9. Mirvox1114

    Mirvox1114

    Joined:
    Mar 31, 2022
    Posts:
    6
    Thanks you so much, it is working now! I didn't use JSON spring, i took easyer path right now(but i doubt it will work later), becouse i want to move on from this script for right now but i will use it when i return to this script.
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using Photon.Pun;
    5. using Photon.Realtime;
    6.  
    7. public class DeckCopy : MonoBehaviourPunCallbacks
    8. {
    9.  
    10.     Item[] player1deck;
    11.  
    12.     Animator animator;
    13.  
    14.     PhotonView view;
    15.  
    16.     GameObject itemPerent1;
    17.     GameObject itemPerent2;
    18.  
    19.     string playerInHierarchy;
    20.  
    21.     void Start()
    22.     {
    23.         animator = GetComponent<Animator>();
    24.         animator.SetFloat("animationIndex", 2);
    25.      
    26.         view = GetComponent<PhotonView>();
    27.         ////////////////////////////////////////////////
    28.         player1deck = Deck.instance.TransferDeck();
    29.         playerInHierarchy = player1deck[0].name + "(Clone)";
    30.  
    31.         itemPerent1 = GameObject.Find(playerInHierarchy).gameObject;
    32.         ///////////////////////////////////////////////
    33.  
    34.         ShowMesh(playerInHierarchy, player1deck[1].name, player1deck[2].name, player1deck[3].name);
    35.  
    36.         if (view.IsMine)
    37.         {
    38.             view.RPC("ShowMesh", RpcTarget.AllBuffered, playerInHierarchy, player1deck[1].name, player1deck[2].name, player1deck[3].name);
    39.  
    40.             Debug.Log("ViewIs Rly mine2 (");
    41.         }
    42.     }
    43.  
    44.     public override void OnPlayerEnteredRoom(Player newPlayer)
    45.     {
    46.         Debug.Log("ViewIs Rly mine1 (");
    47.         if (view.IsMine)
    48.         {
    49.             view.RPC("ShowMesh", RpcTarget.AllBuffered,playerInHierarchy, player1deck[1].name, player1deck[2].name, player1deck[3].name);
    50.  
    51.             Debug.Log("ViewIs Rly mine2 (");
    52.         }
    53.      
    54.     }
    55.  
    56.     [PunRPC]
    57.     void ShowMesh(string Hero, string Sword, string Shield, string Potion)
    58.     {
    59.             itemPerent2 = GameObject.Find(Hero).gameObject;
    60.             itemPerent2.transform.Find(Sword).gameObject.SetActive(true);
    61.             itemPerent2.transform.Find(Shield).gameObject.SetActive(true);
    62.             itemPerent2.transform.Find(Potion).gameObject.SetActive(true);
    63.     }
    64.  
    65. }
    66.  
     
    Munchy2007 likes this.