Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice
  3. Dismiss Notice

Third Party [Photon] Finding PhotonNetwork.InstantiateSceneObject's object on clients

Discussion in 'Multiplayer' started by notrami, Aug 23, 2017.

  1. notrami

    notrami

    Joined:
    Aug 23, 2017
    Posts:
    4
    In my game, prefabs need to be spawned and some of its components must be modified; for instance, I need to instantiate an object and immediately child it to the player who issued the instantiate RPC to the MasterClient.

    I've tried many solutions but I always get trouble with clients. In this case, GameObject.Find (chargeParticlesName + "(Clone)"); returns null (as the client). This works flawlessly when the MasterClient does it.
    Code (CSharp):
    1.  
    2.     void Start() {
    3.         (...)
    4.         chargeParticlesName = chargeParticlesPath.Split ('/').Last (); // chargeParticlesPath is the path to the prefab
    5.     }
    Code (CSharp):
    1.  
    2.     [PunRPC] // When I call this RPC, PhotonTargets is AllBuffered.
    3.     void Charge_Spawn(string path, Vector3 pos, Quaternion rot) {
    4.         if (PhotonNetwork.isMasterClient)
    5.             PhotonNetwork.InstantiateSceneObject (path, pos, rot, 0, null);
    6.      
    7.         chargeParticles = GameObject.Find (chargeParticlesName + "(Clone)");
    8.         chargeParticles.transform.SetParent (transform);
    9.         chargeParticles.transform.position = Vector3.zero;
    10.         chargeParticles.transform.localPosition = Vector3.forward;
    11.     }
    Why does this happen? Has anyone done this before for their game?
    Thanks in advance.
     
    Last edited: Aug 23, 2017
  2. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,744
    Why not try passing the viewID of the parent object in the instantiationdata of the child object, and then override OnPhotonInstantiate in the child object script and use PhotonView.Find(instantiationdata[index]) to retrieve the parent object which you can then use as the argument for the transform.SetParent() call.

    You can also set the position and rotation at this point, and as it will run on all clients when the object is instantiated, they will all be synchronised.
     
    tobiass and notrami like this.
  3. notrami

    notrami

    Joined:
    Aug 23, 2017
    Posts:
    4
    Thank you so much. I never came across the data parameter in the docs, this solves everything.
     
  4. nizarkadri8

    nizarkadri8

    Joined:
    Apr 27, 2020
    Posts:
    4
    Do you know how to change the name of the object from "somename(clone)" to some other name, I treida lot but it only changes the name on master client's side and not on the other clients
     
  5. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,744
    You need to use an RPC to effect changes on the other clients. Send the new name as an argument in the RPC method.
     
  6. nizarkadri8

    nizarkadri8

    Joined:
    Apr 27, 2020
    Posts:
    4
    I tried doing that but it says " RPC cant send objects", i have 9 objects per players to instantiate.

    This is what i did but it didn't work.


    public void FirstInitializeBluePeices() {

    for (int i = 0; i < GreenPos.Length; i++)
    {
    bluePieces = PhotonNetwork.Instantiate(playerPieceBlue.name, BluePos, Quaternion.identity );

    bluePieces.GetComponent<PhotonView>().RPC("changeBlueName", RpcTarget.AllBuffered,i);

    }
    }

    [PunRPC]
    public void changeBlueName(int i)
    {
    bluepieces.name = "whatever name"; //bluepieces is a global array
    }
     
  7. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,744
    If you want to set the name when it's instantiated, send the name in the instantiation data and you can retrieve it in OnPhotonInstantiate callback and set the game object name there.

    Excerpt from the Photon PUN docs https://doc.photonengine.com/en-us/pun/current/gameplay/instantiation

    Custom Instantiation Data
    You can send some initial custom data when the instantiation call. Just make use of the last parameter in the PhotonNetwork.Instantiate* method.

    This has two main advantages:

    • save traffic by avoiding extra messages: we don't have to use a separate RPC or RaiseEvent call for synchronizing this kind of information
    • timing: the data exchanged is available on the time of the prefab instantiation which could be useful to do some initialization
    The instantiation data is an object array (object[]) of anything Photon can serialize.

    Example:

    Instantiate with custom data:
    Code (CSharp):
    1. object[] myCustomInitData = GetInitData();
    2. PhotonNetwork.Instantiate("MyPrefabName", new Vector3(0, 0, 0), Quaternion.identity, 0, myCustomInitData);
    Receive custom data:

    Code (CSharp):
    1. public void OnPhotonInstantiate(PhotonMessageInfo info)
    2. {
    3.    object[] instantiationData = info.photonView.InstantiationData;
    4.    // ...
    5. }
    What can Photon Serialise? https://doc.photonengine.com/en-US/realtime/current/reference/serialization-in-photon
    You can also add custom types to be serialised by following the example given.
     
  8. nizarkadri8

    nizarkadri8

    Joined:
    Apr 27, 2020
    Posts:
    4
    I had seen this too, but didn't got any idea how can i use it to rename , because i am instantiating two times in two different loops.So which data will i get when i overload OnPhotonInstantiate() , Also i tried printing the contents of object[] instantiationData = info.photonView.InstantiationData; But for some reason the print statement also doesnt showup, can you please help me out
     
  9. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,744
    It doesn't matter where you perform the instantiation, the callback will happen on the instantiated object when it gets created on each client, as long as you have registered the script as a callback target for IPunInstantiateMagicCallback.

    You'll need to post the script that you tried this in for anyone to be to help with why it isn't working.
     
    Last edited: Aug 28, 2020
  10. nizarkadri8

    nizarkadri8

    Joined:
    Apr 27, 2020
    Posts:
    4
    public class PlacePlayers : MonoBehaviourPun
    {
    // Start is called before the first frame update
    public static string Winner;
    public GameObject playerPieceBlue;
    public GameObject playerPieceGreen;
    public GameObject[] greenPieces = new GameObject[9];
    public GameObject[] bluePieces = new GameObject[9];



    void Start()
    {
    if (PhotonNetwork.IsMasterClient)
    {
    FirstInitializeBluePeices();
    }

    if (!PhotonNetwork.IsMasterClient)
    {
    FirstInitializeGreenPeices();
    }
    }


    public void OnPhotonInstantiate(PhotonMessageInfo info)
    {
    object[] instantiationData = info.photonView.InstantiationData;
    Debug.Log(instantiationData); //Trying to see whats coming in instantiation data

    }
    public void FirstInitializeBluePeices() {
    for (int i = 0; i < GreenPos.Length; i++)
    {
    bluePieces = PhotonNetwork.Instantiate(playerPieceBlue.name, BluePos, Quaternion.identity,0,bluePieces);
    }
    }


    public void FirstInitializeGreenPeices()
    {
    for (int i = 0; i < GreenPos.Length; i++)
    {
    greenPieces = PhotonNetwork.Instantiate(playerPieceGreen.name, GreenPos, Quaternion.identity,0,greenPieces);

    }
    }
    }
     
  11. Munchy2007

    Munchy2007

    Joined:
    Jun 16, 2013
    Posts:
    1,744
    For the OnPhotonInstantiate callback to work you need to implement the IPunInstantiateMagicCallback interface and register as a callback target.

    I've amended your script accordingly, and you should now at least have the callback working.

    Also you should learn how to use code tags properly if you continue to ask for advice concerning your scripts.

    Code (CSharp):
    1. using Photon.Pun;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class PlacePlayers : MonoBehaviourPun, IPunInstantiateMagicCallback
    7. {
    8.     // Start is called before the first frame update
    9.     public static string Winner;
    10.     public GameObject playerPieceBlue;
    11.     public GameObject playerPieceGreen;
    12.     public GameObject[] greenPieces = new GameObject[9];
    13.     public GameObject[] bluePieces = new GameObject[9];
    14.  
    15.     private void OnEnable()
    16.     {
    17.         PhotonNetwork.AddCallbackTarget(this);
    18.     }
    19.  
    20.     private void OnDisable()
    21.     {
    22.         PhotonNetwork.RemoveCallbackTarget(this);
    23.     }
    24.  
    25.     void Start()
    26.     {
    27.         if (PhotonNetwork.IsMasterClient)
    28.         {
    29.             FirstInitializeBluePeices();
    30.         }
    31.  
    32.         if (!PhotonNetwork.IsMasterClient)
    33.         {
    34.             FirstInitializeGreenPeices();
    35.         }
    36.     }
    37.  
    38.  
    39.     public void OnPhotonInstantiate(PhotonMessageInfo info)
    40.     {
    41.         object[] instantiationData = info.photonView.InstantiationData;
    42.         Debug.Log(instantiationData); //Trying to see whats coming in instantiation data
    43.  
    44.     }
    45.     public void FirstInitializeBluePeices()
    46.     {
    47.         for (int i = 0; i < GreenPos.Length; i++)
    48.         {
    49.             bluePieces = PhotonNetwork.Instantiate(playerPieceBlue.name, BluePos, Quaternion.identity, 0, bluePieces);
    50.         }
    51.     }
    52.  
    53.  
    54.     public void FirstInitializeGreenPeices()
    55.     {
    56.         for (int i = 0; i < GreenPos.Length; i++)
    57.         {
    58.             greenPieces = PhotonNetwork.Instantiate(playerPieceGreen.name, GreenPos, Quaternion.identity, 0, greenPieces);
    59.  
    60.         }
    61.     }
    62. }